From 7b4377ad9d8a7205416df8d6217ef2b010f89481 Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Wed, 22 Jan 2025 16:07:17 +0100 Subject: vendor: delete --- vendor/github.com/quasilyte/go-ruleguard/LICENSE | 29 - .../github.com/quasilyte/go-ruleguard/dsl/LICENSE | 29 - .../quasilyte/go-ruleguard/dsl/bundle.go | 19 - vendor/github.com/quasilyte/go-ruleguard/dsl/do.go | 19 - .../github.com/quasilyte/go-ruleguard/dsl/dsl.go | 361 ----- .../quasilyte/go-ruleguard/dsl/filter.go | 24 - .../quasilyte/go-ruleguard/dsl/internal.go | 6 - .../quasilyte/go-ruleguard/dsl/types/ext.go | 21 - .../quasilyte/go-ruleguard/dsl/types/type_impl.go | 17 - .../quasilyte/go-ruleguard/dsl/types/types.go | 68 - .../quasilyte/go-ruleguard/internal/goenv/goenv.go | 34 - .../go-ruleguard/internal/golist/golist.go | 30 - .../internal/xsrcimporter/xsrcimporter.go | 29 - .../go-ruleguard/internal/xtypes/xtypes.go | 270 ---- .../quasilyte/go-ruleguard/ruleguard/ast_walker.go | 369 ----- .../quasilyte/go-ruleguard/ruleguard/bundle.go | 19 - .../quasilyte/go-ruleguard/ruleguard/engine.go | 270 ---- .../quasilyte/go-ruleguard/ruleguard/filters.go | 835 ---------- .../quasilyte/go-ruleguard/ruleguard/go_version.go | 58 - .../quasilyte/go-ruleguard/ruleguard/gorule.go | 154 -- .../go-ruleguard/ruleguard/goutil/goutil.go | 67 - .../go-ruleguard/ruleguard/goutil/resolve.go | 33 - .../quasilyte/go-ruleguard/ruleguard/importer.go | 95 -- .../go-ruleguard/ruleguard/ir/filter_op.gen.go | 282 ---- .../go-ruleguard/ruleguard/ir/gen_filter_op.go | 148 -- .../quasilyte/go-ruleguard/ruleguard/ir/ir.go | 113 -- .../quasilyte/go-ruleguard/ruleguard/ir_loader.go | 890 ----------- .../quasilyte/go-ruleguard/ruleguard/ir_utils.go | 41 - .../go-ruleguard/ruleguard/irconv/irconv.go | 857 ---------- .../quasilyte/go-ruleguard/ruleguard/libdsl.go | 401 ----- .../quasilyte/go-ruleguard/ruleguard/match_data.go | 19 - .../quasilyte/go-ruleguard/ruleguard/nodepath.go | 49 - .../go-ruleguard/ruleguard/profiling/no_labels.go | 16 - .../ruleguard/profiling/with_labels.go | 21 - .../go-ruleguard/ruleguard/quasigo/compile.go | 869 ---------- .../go-ruleguard/ruleguard/quasigo/debug_info.go | 17 - .../go-ruleguard/ruleguard/quasigo/disasm.go | 84 - .../go-ruleguard/ruleguard/quasigo/env.go | 42 - .../go-ruleguard/ruleguard/quasigo/eval.go | 265 ---- .../go-ruleguard/ruleguard/quasigo/gen_opcodes.go | 192 --- .../ruleguard/quasigo/opcode_string.go | 69 - .../go-ruleguard/ruleguard/quasigo/opcodes.gen.go | 249 --- .../go-ruleguard/ruleguard/quasigo/quasigo.go | 199 --- .../ruleguard/quasigo/stdlib/qfmt/qfmt.go | 17 - .../ruleguard/quasigo/stdlib/qstrconv/qstrconv.go | 24 - .../ruleguard/quasigo/stdlib/qstrings/qstrings.go | 62 - .../go-ruleguard/ruleguard/quasigo/utils.go | 60 - .../quasilyte/go-ruleguard/ruleguard/ruleguard.go | 221 --- .../quasilyte/go-ruleguard/ruleguard/runner.go | 562 ------- .../go-ruleguard/ruleguard/textmatch/compile.go | 84 - .../go-ruleguard/ruleguard/textmatch/matchers.go | 72 - .../go-ruleguard/ruleguard/textmatch/textmatch.go | 26 - .../ruleguard/typematch/patternop_string.go | 36 - .../go-ruleguard/ruleguard/typematch/typematch.go | 607 ------- .../quasilyte/go-ruleguard/ruleguard/utils.go | 304 ---- vendor/github.com/quasilyte/gogrep/.gitignore | 4 - vendor/github.com/quasilyte/gogrep/.golangci.yml | 49 - vendor/github.com/quasilyte/gogrep/LICENSE | 33 - vendor/github.com/quasilyte/gogrep/Makefile | 19 - vendor/github.com/quasilyte/gogrep/README.md | 41 - vendor/github.com/quasilyte/gogrep/compile.go | 1264 --------------- .../github.com/quasilyte/gogrep/compile_import.go | 57 - .../github.com/quasilyte/gogrep/gen_operations.go | 366 ----- vendor/github.com/quasilyte/gogrep/gogrep.go | 187 --- vendor/github.com/quasilyte/gogrep/instructions.go | 116 -- .../quasilyte/gogrep/internal/stdinfo/stdinfo.go | 151 -- vendor/github.com/quasilyte/gogrep/match.go | 1024 ------------ .../github.com/quasilyte/gogrep/nodetag/nodetag.go | 287 ---- .../quasilyte/gogrep/operation_string.go | 154 -- .../github.com/quasilyte/gogrep/operations.gen.go | 1671 -------------------- vendor/github.com/quasilyte/gogrep/parse.go | 403 ----- vendor/github.com/quasilyte/gogrep/slices.go | 150 -- vendor/github.com/quasilyte/regex/syntax/LICENSE | 21 - vendor/github.com/quasilyte/regex/syntax/README.md | 29 - vendor/github.com/quasilyte/regex/syntax/ast.go | 64 - vendor/github.com/quasilyte/regex/syntax/errors.go | 27 - vendor/github.com/quasilyte/regex/syntax/lexer.go | 454 ------ .../github.com/quasilyte/regex/syntax/operation.go | 195 --- .../quasilyte/regex/syntax/operation_string.go | 59 - vendor/github.com/quasilyte/regex/syntax/parser.go | 503 ------ vendor/github.com/quasilyte/regex/syntax/pos.go | 10 - .../quasilyte/regex/syntax/tokenkind_string.go | 59 - vendor/github.com/quasilyte/regex/syntax/utils.go | 30 - vendor/github.com/quasilyte/stdinfo/LICENSE | 21 - vendor/github.com/quasilyte/stdinfo/stdinfo.go | 30 - vendor/github.com/quasilyte/stdinfo/stdinfo_gen.go | 274 ---- 86 files changed, 17506 deletions(-) delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/LICENSE delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/LICENSE delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/bundle.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/do.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/dsl.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/filter.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/internal.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/types/ext.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/types/type_impl.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/dsl/types/types.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/golist/golist.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/xtypes/xtypes.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/resolve.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/libdsl.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/match_data.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/no_labels.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/with_labels.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/compile.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/debug_info.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/disasm.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/env.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/eval.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/gen_opcodes.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcode_string.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcodes.gen.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/quasigo.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qfmt/qfmt.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrconv/qstrconv.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrings/qstrings.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/utils.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go delete mode 100644 vendor/github.com/quasilyte/gogrep/.gitignore delete mode 100644 vendor/github.com/quasilyte/gogrep/.golangci.yml delete mode 100644 vendor/github.com/quasilyte/gogrep/LICENSE delete mode 100644 vendor/github.com/quasilyte/gogrep/Makefile delete mode 100644 vendor/github.com/quasilyte/gogrep/README.md delete mode 100644 vendor/github.com/quasilyte/gogrep/compile.go delete mode 100644 vendor/github.com/quasilyte/gogrep/compile_import.go delete mode 100644 vendor/github.com/quasilyte/gogrep/gen_operations.go delete mode 100644 vendor/github.com/quasilyte/gogrep/gogrep.go delete mode 100644 vendor/github.com/quasilyte/gogrep/instructions.go delete mode 100644 vendor/github.com/quasilyte/gogrep/internal/stdinfo/stdinfo.go delete mode 100644 vendor/github.com/quasilyte/gogrep/match.go delete mode 100644 vendor/github.com/quasilyte/gogrep/nodetag/nodetag.go delete mode 100644 vendor/github.com/quasilyte/gogrep/operation_string.go delete mode 100644 vendor/github.com/quasilyte/gogrep/operations.gen.go delete mode 100644 vendor/github.com/quasilyte/gogrep/parse.go delete mode 100644 vendor/github.com/quasilyte/gogrep/slices.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/LICENSE delete mode 100644 vendor/github.com/quasilyte/regex/syntax/README.md delete mode 100644 vendor/github.com/quasilyte/regex/syntax/ast.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/errors.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/lexer.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/operation.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/operation_string.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/parser.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/pos.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/tokenkind_string.go delete mode 100644 vendor/github.com/quasilyte/regex/syntax/utils.go delete mode 100644 vendor/github.com/quasilyte/stdinfo/LICENSE delete mode 100644 vendor/github.com/quasilyte/stdinfo/stdinfo.go delete mode 100644 vendor/github.com/quasilyte/stdinfo/stdinfo_gen.go (limited to 'vendor/github.com/quasilyte') diff --git a/vendor/github.com/quasilyte/go-ruleguard/LICENSE b/vendor/github.com/quasilyte/go-ruleguard/LICENSE deleted file mode 100644 index 558f81ff2..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2022, Iskander (Alex) Sharipov / quasilyte -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/LICENSE b/vendor/github.com/quasilyte/go-ruleguard/dsl/LICENSE deleted file mode 100644 index 558f81ff2..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2022, Iskander (Alex) Sharipov / quasilyte -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/bundle.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/bundle.go deleted file mode 100644 index 45a9455d8..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/bundle.go +++ /dev/null @@ -1,19 +0,0 @@ -package dsl - -// Bundle is a rules file export manifest. -type Bundle struct { - // TODO: figure out which fields we might want to add here. -} - -// ImportRules imports all rules from the bundle and prefixes them with a specified string. -// -// Empty string prefix is something like "dot import" in Go. -// Group name collisions will result in an error. -// -// Only packages that have an exported Bundle variable can be imported. -// -// Note: right now imported bundle can't import other bundles. -// This is not a fundamental limitation but rather a precaution -// measure before we understand how it should work better. -// If you need this feature, please open an issue at github.com/quasilyte/go-ruleguard. -func ImportRules(prefix string, bundle Bundle) {} diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/do.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/do.go deleted file mode 100644 index 86bc163a7..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/do.go +++ /dev/null @@ -1,19 +0,0 @@ -package dsl - -import ( - "github.com/quasilyte/go-ruleguard/dsl/types" -) - -type DoContext struct{} - -func (*DoContext) Var(varname string) *DoVar { return nil } - -func (*DoContext) SetReport(report string) {} - -func (*DoContext) SetSuggest(suggest string) {} - -type DoVar struct{} - -func (*DoVar) Text() string { return "" } - -func (*DoVar) Type() types.Type { return nil } diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/dsl.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/dsl.go deleted file mode 100644 index d3c73bddd..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/dsl.go +++ /dev/null @@ -1,361 +0,0 @@ -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 diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/filter.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/filter.go deleted file mode 100644 index cef880098..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/filter.go +++ /dev/null @@ -1,24 +0,0 @@ -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. -// It uses the ruleguard.Context.Sizes to calculate the result. -func (*VarFilterContext) SizeOf(x types.Type) int { return 0 } - -// GetType finds a type value by a given name. -// If a type can't be found (or a name is malformed), this function panics. -func (*VarFilterContext) GetType(name typeName) 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 typeName) *types.Interface { return nil } diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/internal.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/internal.go deleted file mode 100644 index 3bb6d85dc..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/internal.go +++ /dev/null @@ -1,6 +0,0 @@ -package dsl - -var boolResult bool -var intResult int - -var underlyingType ExprType diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/types/ext.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/types/ext.go deleted file mode 100644 index 82595ff30..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/types/ext.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -// AsArray is a type-assert like operation, x.(*Array), but never panics. -// Returns nil if type is not an array. -func AsArray(x Type) *Array { return nil } - -// AsSlice is a type-assert like operation, x.(*Slice), but never panics. -// Returns nil if type is not an array. -func AsSlice(x Type) *Slice { return nil } - -// 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 } - -// AsStruct is a type-assert like operation, x.(*Struct), but never panics. -// Returns nil if type is not a struct. -func AsStruct(x Type) *Struct { 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/vendor/github.com/quasilyte/go-ruleguard/dsl/types/type_impl.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/types/type_impl.go deleted file mode 100644 index 9fc71d753..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/types/type_impl.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -// Method stubs to make various types implement Type interface. -// -// Nothing interesting here, hence it's moved to a separate file. - -func (*Array) String() string { return "" } -func (*Slice) String() string { return "" } -func (*Pointer) String() string { return "" } -func (*Interface) String() string { return "" } -func (*Struct) String() string { return "" } - -func (*Array) Underlying() Type { return nil } -func (*Slice) Underlying() Type { return nil } -func (*Pointer) Underlying() Type { return nil } -func (*Interface) Underlying() Type { return nil } -func (*Struct) Underlying() Type { return nil } diff --git a/vendor/github.com/quasilyte/go-ruleguard/dsl/types/types.go b/vendor/github.com/quasilyte/go-ruleguard/dsl/types/types.go deleted file mode 100644 index b6be7cc35..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/dsl/types/types.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 ( - // An Array represents an array type. - Array struct{} - - // A Slice represents a slice type. - Slice struct{} - - // A Pointer represents a pointer type. - Pointer struct{} - - // An Interface represents an interface type. - Interface struct{} - - // A struct represents a struct type. - Struct struct{} -) - -// NewArray returns a new array type for the given element type and length. -// A negative length indicates an unknown length. -func NewArray(elem Type, len int) *Array { return nil } - -// Elem returns element type of array. -func (*Array) Elem() Type { return nil } - -// NewSlice returns a new slice type for the given element type. -func NewSlice(elem Type) *Slice { return nil } - -// Elem returns element type of slice. -func (*Slice) Elem() Type { return nil } - -// Len returns the length of array. -// A negative result indicates an unknown length. -func (*Array) Len() int { return 0 } - -// 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 } - -func (*Struct) NumFields() int { return 0 } - -func (*Struct) Field(i int) *Var { return nil } - -type Var struct{} - -func (*Var) Embedded() bool { return false } - -func (*Var) Type() Type { return nil } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go b/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go deleted file mode 100644 index 52d0f5204..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go +++ /dev/null @@ -1,34 +0,0 @@ -package goenv - -import ( - "errors" - "os/exec" - "strings" -) - -func Read() (map[string]string, error) { - // pass in a fixed set of var names to avoid needing to unescape output - // pass in literals here instead of a variable list to avoid security linter warnings about command injection - out, err := exec.Command("go", "env", "GOROOT", "GOPATH", "GOARCH", "GOOS", "CGO_ENABLED").CombinedOutput() - if err != nil { - return nil, err - } - return parseGoEnv([]string{"GOROOT", "GOPATH", "GOARCH", "GOOS", "CGO_ENABLED"}, out) -} - -func parseGoEnv(varNames []string, data []byte) (map[string]string, error) { - vars := make(map[string]string) - - lines := strings.Split(strings.ReplaceAll(string(data), "\r\n", "\n"), "\n") - for i, varName := range varNames { - if i < len(lines) && len(lines[i]) > 0 { - vars[varName] = lines[i] - } - } - - if len(vars) == 0 { - return nil, errors.New("empty env set") - } - - return vars, nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/golist/golist.go b/vendor/github.com/quasilyte/go-ruleguard/internal/golist/golist.go deleted file mode 100644 index 50f9cca0b..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/golist/golist.go +++ /dev/null @@ -1,30 +0,0 @@ -package golist - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "os/exec" -) - -// Package is `go list --json` output structure. -type Package struct { - Dir string // directory containing package sources - ImportPath string // import path of package in dir - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) -} - -// JSON runs `go list --json` for the specified pkgName and returns the parsed JSON. -func JSON(pkgPath string) (*Package, error) { - out, err := exec.Command("go", "list", "--json", pkgPath).CombinedOutput() - if err != nil { - return nil, fmt.Errorf("go list error (%v): %s", err, out) - } - - var pkg Package - if err := json.NewDecoder(bytes.NewReader(out)).Decode(&pkg); err != io.EOF && err != nil { - return nil, err - } - return &pkg, nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go b/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go deleted file mode 100644 index 3b58f97c7..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go +++ /dev/null @@ -1,29 +0,0 @@ -package xsrcimporter - -import ( - "go/build" - "go/importer" - "go/token" - "go/types" - "unsafe" -) - -func New(ctxt *build.Context, fset *token.FileSet) types.Importer { - imp := importer.ForCompiler(fset, "source", nil) - ifaceVal := *(*iface)(unsafe.Pointer(&imp)) - srcImp := (*srcImporter)(ifaceVal.data) - srcImp.ctxt = ctxt - return imp -} - -type iface struct { - _ *byte - data unsafe.Pointer -} - -type srcImporter struct { - ctxt *build.Context - _ *token.FileSet - _ types.Sizes - _ map[string]*types.Package -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/xtypes/xtypes.go b/vendor/github.com/quasilyte/go-ruleguard/internal/xtypes/xtypes.go deleted file mode 100644 index d29573a6f..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/xtypes/xtypes.go +++ /dev/null @@ -1,270 +0,0 @@ -package xtypes - -import ( - "go/types" - - "golang.org/x/exp/typeparams" -) - -// Implements reports whether type v implements iface. -// -// Unlike types.Implements(), it permits X and Y named types -// to be considered identical even if their addresses are different. -func Implements(v types.Type, iface *types.Interface) bool { - if iface.Empty() { - return true - } - - if v, _ := v.Underlying().(*types.Interface); v != nil { - for i := 0; i < iface.NumMethods(); i++ { - m := iface.Method(i) - obj, _, _ := types.LookupFieldOrMethod(v, false, m.Pkg(), m.Name()) - switch { - case obj == nil: - return false - case !Identical(obj.Type(), m.Type()): - return false - } - } - return true - } - - // A concrete type v implements iface if it implements all methods of iface. - for i := 0; i < iface.NumMethods(); i++ { - m := iface.Method(i) - - obj, _, _ := types.LookupFieldOrMethod(v, false, m.Pkg(), m.Name()) - if obj == nil { - return false - } - - f, ok := obj.(*types.Func) - if !ok { - return false - } - - if !Identical(f.Type(), m.Type()) { - return false - } - } - - return true -} - -// Identical reports whether x and y are identical types. -// -// Unlike types.Identical(), it permits X and Y named types -// to be considered identical even if their addresses are different. -func Identical(x, y types.Type) bool { - return typeIdentical(x, y, nil) -} - -func typeIdentical(x, y types.Type, p *ifacePair) bool { - if x == y { - return true - } - - switch x := x.(type) { - case *types.Basic: - // Basic types are singletons except for the rune and byte - // aliases, thus we cannot solely rely on the x == y check - // above. See also comment in TypeName.IsAlias. - if y, ok := y.(*types.Basic); ok { - return x.Kind() == y.Kind() - } - - case *types.Array: - // Two array types are identical if they have identical element types - // and the same array length. - if y, ok := y.(*types.Array); ok { - // If one or both array lengths are unknown (< 0) due to some error, - // assume they are the same to avoid spurious follow-on errors. - return (x.Len() < 0 || y.Len() < 0 || x.Len() == y.Len()) && typeIdentical(x.Elem(), y.Elem(), p) - } - - case *types.Slice: - // Two slice types are identical if they have identical element types. - if y, ok := y.(*types.Slice); ok { - return typeIdentical(x.Elem(), y.Elem(), p) - } - - case *types.Struct: - // Two struct types are identical if they have the same sequence of fields, - // and if corresponding fields have the same names, and identical types, - // and identical tags. Two embedded fields are considered to have the same - // name. Lower-case field names from different packages are always different. - if y, ok := y.(*types.Struct); ok { - if x.NumFields() == y.NumFields() { - for i := 0; i < x.NumFields(); i++ { - f := x.Field(i) - g := y.Field(i) - if f.Embedded() != g.Embedded() || !sameID(f, g.Pkg(), g.Name()) || !typeIdentical(f.Type(), g.Type(), p) { - return false - } - } - return true - } - } - - case *types.Pointer: - // Two pointer types are identical if they have identical base types. - if y, ok := y.(*types.Pointer); ok { - return typeIdentical(x.Elem(), y.Elem(), p) - } - - case *types.Tuple: - // Two tuples types are identical if they have the same number of elements - // and corresponding elements have identical types. - if y, ok := y.(*types.Tuple); ok { - if x.Len() == y.Len() { - if x != nil { - for i := 0; i < x.Len(); i++ { - v := x.At(i) - w := y.At(i) - if !typeIdentical(v.Type(), w.Type(), p) { - return false - } - } - } - return true - } - } - - case *types.Signature: - // Two function types are identical if they have the same number of parameters - // and result values, corresponding parameter and result types are identical, - // and either both functions are variadic or neither is. Parameter and result - // names are not required to match. - if y, ok := y.(*types.Signature); ok { - return x.Variadic() == y.Variadic() && - typeIdentical(x.Params(), y.Params(), p) && - typeIdentical(x.Results(), y.Results(), p) - } - - case *typeparams.Union: - // TODO(quasilyte): do we want to match generic union types too? - // It would require copying a lot of code from the go/types. - return false - - case *types.Interface: - // Two interface types are identical if they have the same set of methods with - // the same names and identical function types. Lower-case method names from - // different packages are always different. The order of the methods is irrelevant. - if y, ok := y.(*types.Interface); ok { - if x.NumMethods() != y.NumMethods() { - return false - } - // Interface types are the only types where cycles can occur - // that are not "terminated" via named types; and such cycles - // can only be created via method parameter types that are - // anonymous interfaces (directly or indirectly) embedding - // the current interface. Example: - // - // type T interface { - // m() interface{T} - // } - // - // If two such (differently named) interfaces are compared, - // endless recursion occurs if the cycle is not detected. - // - // If x and y were compared before, they must be equal - // (if they were not, the recursion would have stopped); - // search the ifacePair stack for the same pair. - // - // This is a quadratic algorithm, but in practice these stacks - // are extremely short (bounded by the nesting depth of interface - // type declarations that recur via parameter types, an extremely - // rare occurrence). An alternative implementation might use a - // "visited" map, but that is probably less efficient overall. - q := &ifacePair{x, y, p} - for p != nil { - if p.identical(q) { - return true // same pair was compared before - } - p = p.prev - } - for i := 0; i < x.NumMethods(); i++ { - f := x.Method(i) - g := y.Method(i) - if f.Id() != g.Id() || !typeIdentical(f.Type(), g.Type(), q) { - return false - } - } - return true - } - - case *types.Map: - // Two map types are identical if they have identical key and value types. - if y, ok := y.(*types.Map); ok { - return typeIdentical(x.Key(), y.Key(), p) && typeIdentical(x.Elem(), y.Elem(), p) - } - - case *types.Chan: - // Two channel types are identical if they have identical value types - // and the same direction. - if y, ok := y.(*types.Chan); ok { - return x.Dir() == y.Dir() && typeIdentical(x.Elem(), y.Elem(), p) - } - - case *types.Named: - // Two named types are identical if their type names originate - // in the same type declaration. - y, ok := y.(*types.Named) - if !ok { - return false - } - if x.Obj() == y.Obj() { - return true - } - return sameID(x.Obj(), y.Obj().Pkg(), y.Obj().Name()) - - case *typeparams.TypeParam: - // nothing to do (x and y being equal is caught in the very beginning of this function) - - case *types.Alias: - // an alias type is identical if the type it's an alias of is identical to it. - return typeIdentical(types.Unalias(x), y, p) - - case nil: - // avoid a crash in case of nil type - - default: - panic("unreachable") - } - - return false -} - -// An ifacePair is a node in a stack of interface type pairs compared for identity. -type ifacePair struct { - x *types.Interface - y *types.Interface - prev *ifacePair -} - -func (p *ifacePair) identical(q *ifacePair) bool { - return (p.x == q.x && p.y == q.y) || - (p.x == q.y && p.y == q.x) -} - -func sameID(obj types.Object, pkg *types.Package, name string) bool { - // spec: - // "Two identifiers are different if they are spelled differently, - // or if they appear in different packages and are not exported. - // Otherwise, they are the same." - if name != obj.Name() { - return false - } - // obj.Name == name - if obj.Exported() { - return true - } - // not exported, so packages must be the same (pkg == nil for - // fields in Universe scope; this can only happen for types - // introduced via Eval) - if pkg == nil || obj.Pkg() == nil { - return pkg == obj.Pkg() - } - // pkg != nil && obj.pkg != nil - return pkg.Path() == obj.Pkg().Path() -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go deleted file mode 100644 index c52a5a822..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go +++ /dev/null @@ -1,369 +0,0 @@ -package ruleguard - -import ( - "go/ast" - "go/constant" - - "github.com/quasilyte/gogrep/nodetag" -) - -type astWalker struct { - nodePath *nodePath - - filterParams *filterParams - - visit func(ast.Node, nodetag.Value) -} - -func (w *astWalker) Walk(root ast.Node, visit func(ast.Node, nodetag.Value)) { - w.visit = visit - w.walk(root) -} - -func (w *astWalker) walkIdentList(list []*ast.Ident) { - for _, x := range list { - w.walk(x) - } -} - -func (w *astWalker) walkExprList(list []ast.Expr) { - for _, x := range list { - w.walk(x) - } -} - -func (w *astWalker) walkStmtList(list []ast.Stmt) { - for _, x := range list { - w.walk(x) - } -} - -func (w *astWalker) walkDeclList(list []ast.Decl) { - for _, x := range list { - w.walk(x) - } -} - -func (w *astWalker) walk(n ast.Node) { - w.nodePath.Push(n) - defer w.nodePath.Pop() - - switch n := n.(type) { - case *ast.Field: - // TODO: handle field types. - // See #252 - w.walkIdentList(n.Names) - w.walk(n.Type) - - case *ast.FieldList: - for _, f := range n.List { - w.walk(f) - } - - case *ast.Ellipsis: - w.visit(n, nodetag.Ellipsis) - if n.Elt != nil { - w.walk(n.Elt) - } - - case *ast.FuncLit: - w.visit(n, nodetag.FuncLit) - w.walk(n.Type) - w.walk(n.Body) - - case *ast.CompositeLit: - w.visit(n, nodetag.CompositeLit) - if n.Type != nil { - w.walk(n.Type) - } - w.walkExprList(n.Elts) - - case *ast.ParenExpr: - w.visit(n, nodetag.ParenExpr) - w.walk(n.X) - - case *ast.SelectorExpr: - w.visit(n, nodetag.SelectorExpr) - w.walk(n.X) - w.walk(n.Sel) - - case *ast.IndexExpr: - w.visit(n, nodetag.IndexExpr) - w.walk(n.X) - w.walk(n.Index) - - case *ast.SliceExpr: - w.visit(n, nodetag.SliceExpr) - w.walk(n.X) - if n.Low != nil { - w.walk(n.Low) - } - if n.High != nil { - w.walk(n.High) - } - if n.Max != nil { - w.walk(n.Max) - } - - case *ast.TypeAssertExpr: - w.visit(n, nodetag.TypeAssertExpr) - w.walk(n.X) - if n.Type != nil { - w.walk(n.Type) - } - - case *ast.CallExpr: - w.visit(n, nodetag.CallExpr) - w.walk(n.Fun) - w.walkExprList(n.Args) - - case *ast.StarExpr: - w.visit(n, nodetag.StarExpr) - w.walk(n.X) - - case *ast.UnaryExpr: - w.visit(n, nodetag.UnaryExpr) - w.walk(n.X) - - case *ast.BinaryExpr: - w.visit(n, nodetag.BinaryExpr) - w.walk(n.X) - w.walk(n.Y) - - case *ast.KeyValueExpr: - w.visit(n, nodetag.KeyValueExpr) - w.walk(n.Key) - w.walk(n.Value) - - case *ast.ArrayType: - w.visit(n, nodetag.ArrayType) - if n.Len != nil { - w.walk(n.Len) - } - w.walk(n.Elt) - - case *ast.StructType: - w.visit(n, nodetag.StructType) - w.walk(n.Fields) - - case *ast.FuncType: - w.visit(n, nodetag.FuncType) - if n.Params != nil { - w.walk(n.Params) - } - if n.Results != nil { - w.walk(n.Results) - } - - case *ast.InterfaceType: - w.visit(n, nodetag.InterfaceType) - w.walk(n.Methods) - - case *ast.MapType: - w.visit(n, nodetag.MapType) - w.walk(n.Key) - w.walk(n.Value) - - case *ast.ChanType: - w.visit(n, nodetag.ChanType) - w.walk(n.Value) - - case *ast.DeclStmt: - w.visit(n, nodetag.DeclStmt) - w.walk(n.Decl) - - case *ast.LabeledStmt: - w.visit(n, nodetag.LabeledStmt) - w.walk(n.Label) - w.walk(n.Stmt) - - case *ast.ExprStmt: - w.visit(n, nodetag.ExprStmt) - w.walk(n.X) - - case *ast.SendStmt: - w.visit(n, nodetag.SendStmt) - w.walk(n.Chan) - w.walk(n.Value) - - case *ast.IncDecStmt: - w.visit(n, nodetag.IncDecStmt) - w.walk(n.X) - - case *ast.AssignStmt: - w.visit(n, nodetag.AssignStmt) - w.walkExprList(n.Lhs) - w.walkExprList(n.Rhs) - - case *ast.GoStmt: - w.visit(n, nodetag.GoStmt) - w.walk(n.Call) - - case *ast.DeferStmt: - w.visit(n, nodetag.DeferStmt) - w.walk(n.Call) - - case *ast.ReturnStmt: - w.visit(n, nodetag.ReturnStmt) - w.walkExprList(n.Results) - - case *ast.BranchStmt: - w.visit(n, nodetag.BranchStmt) - if n.Label != nil { - w.walk(n.Label) - } - - case *ast.BlockStmt: - w.visit(n, nodetag.BlockStmt) - w.walkStmtList(n.List) - - case *ast.IfStmt: - w.visit(n, nodetag.IfStmt) - if n.Init != nil { - w.walk(n.Init) - } - w.walk(n.Cond) - deadcode := w.filterParams.deadcode - if !deadcode { - cv := w.filterParams.ctx.Types.Types[n.Cond].Value - if cv != nil { - w.filterParams.deadcode = !deadcode && !constant.BoolVal(cv) - w.walk(n.Body) - w.filterParams.deadcode = !w.filterParams.deadcode - if n.Else != nil { - w.walk(n.Else) - } - w.filterParams.deadcode = deadcode - return - } - } - w.walk(n.Body) - if n.Else != nil { - w.walk(n.Else) - } - - case *ast.CaseClause: - w.visit(n, nodetag.CaseClause) - w.walkExprList(n.List) - w.walkStmtList(n.Body) - - case *ast.SwitchStmt: - w.visit(n, nodetag.SwitchStmt) - if n.Init != nil { - w.walk(n.Init) - } - if n.Tag != nil { - w.walk(n.Tag) - } - w.walk(n.Body) - - case *ast.TypeSwitchStmt: - w.visit(n, nodetag.TypeSwitchStmt) - if n.Init != nil { - w.walk(n.Init) - } - w.walk(n.Assign) - w.walk(n.Body) - - case *ast.CommClause: - w.visit(n, nodetag.CommClause) - if n.Comm != nil { - w.walk(n.Comm) - } - w.walkStmtList(n.Body) - - case *ast.SelectStmt: - w.visit(n, nodetag.SelectStmt) - w.walk(n.Body) - - case *ast.ForStmt: - w.visit(n, nodetag.ForStmt) - if n.Init != nil { - w.walk(n.Init) - } - if n.Cond != nil { - w.walk(n.Cond) - } - if n.Post != nil { - w.walk(n.Post) - } - w.walk(n.Body) - - case *ast.RangeStmt: - w.visit(n, nodetag.RangeStmt) - if n.Key != nil { - w.walk(n.Key) - } - if n.Value != nil { - w.walk(n.Value) - } - w.walk(n.X) - w.walk(n.Body) - - case *ast.ImportSpec: - w.visit(n, nodetag.ImportSpec) - if n.Name != nil { - w.walk(n.Name) - } - w.walk(n.Path) - if n.Comment != nil { - w.walk(n.Comment) - } - - case *ast.ValueSpec: - w.visit(n, nodetag.ValueSpec) - if n.Doc != nil { - w.walk(n.Doc) - } - w.walkIdentList(n.Names) - if n.Type != nil { - w.walk(n.Type) - } - w.walkExprList(n.Values) - if n.Comment != nil { - w.walk(n.Comment) - } - - case *ast.TypeSpec: - w.visit(n, nodetag.TypeSpec) - if n.Doc != nil { - w.walk(n.Doc) - } - w.walk(n.Name) - w.walk(n.Type) - if n.Comment != nil { - w.walk(n.Comment) - } - - case *ast.GenDecl: - w.visit(n, nodetag.GenDecl) - if n.Doc != nil { - w.walk(n.Doc) - } - for _, s := range n.Specs { - w.walk(s) - } - - case *ast.FuncDecl: - w.visit(n, nodetag.FuncDecl) - prevFunc := w.filterParams.currentFunc - w.filterParams.currentFunc = n - if n.Doc != nil { - w.walk(n.Doc) - } - if n.Recv != nil { - w.walk(n.Recv) - } - w.walk(n.Name) - w.walk(n.Type) - if n.Body != nil { - w.walk(n.Body) - } - w.filterParams.currentFunc = prevFunc - - case *ast.File: - w.visit(n, nodetag.File) - w.walk(n.Name) - w.walkDeclList(n.Decls) - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go deleted file mode 100644 index 72a334b9c..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go +++ /dev/null @@ -1,19 +0,0 @@ -package ruleguard - -import ( - "path/filepath" - - "github.com/quasilyte/go-ruleguard/internal/golist" -) - -func findBundleFiles(pkgPath string) ([]string, error) { // nolint - pkg, err := golist.JSON(pkgPath) - if err != nil { - return nil, err - } - files := make([]string, 0, len(pkg.GoFiles)) - for _, f := range pkg.GoFiles { - files = append(files, filepath.Join(pkg.Dir, f)) - } - return files, nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go deleted file mode 100644 index e4cf954ff..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go +++ /dev/null @@ -1,270 +0,0 @@ -package ruleguard - -import ( - "errors" - "fmt" - "go/ast" - "go/build" - "go/token" - "go/types" - "io" - "os" - "sort" - "strings" - "sync" - - "github.com/quasilyte/go-ruleguard/internal/goenv" - "github.com/quasilyte/go-ruleguard/ruleguard/ir" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qfmt" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrconv" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrings" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" - "github.com/quasilyte/stdinfo" -) - -type engine struct { - state *engineState - - ruleSet *goRuleSet -} - -func newEngine() *engine { - return &engine{ - state: newEngineState(), - } -} - -func (e *engine) LoadedGroups() []GoRuleGroup { - result := make([]GoRuleGroup, 0, len(e.ruleSet.groups)) - for _, g := range e.ruleSet.groups { - result = append(result, *g) - } - sort.Slice(result, func(i, j int) bool { - return result[i].Name < result[j].Name - }) - return result -} - -func (e *engine) Load(ctx *LoadContext, buildContext *build.Context, filename string, r io.Reader) error { - data, err := io.ReadAll(r) - if err != nil { - return err - } - imp := newGoImporter(e.state, goImporterConfig{ - fset: ctx.Fset, - debugImports: ctx.DebugImports, - debugPrint: ctx.DebugPrint, - buildContext: buildContext, - }) - irfile, pkg, err := convertAST(ctx, imp, filename, data) - if err != nil { - return err - } - config := irLoaderConfig{ - state: e.state, - pkg: pkg, - ctx: ctx, - importer: imp, - itab: typematch.NewImportsTab(stdinfo.PathByName), - gogrepFset: token.NewFileSet(), - } - l := newIRLoader(config) - rset, err := l.LoadFile(filename, irfile) - if err != nil { - return err - } - - if e.ruleSet == nil { - e.ruleSet = rset - } else { - combinedRuleSet, err := mergeRuleSets([]*goRuleSet{e.ruleSet, rset}) - if err != nil { - return err - } - e.ruleSet = combinedRuleSet - } - - return nil -} - -func (e *engine) LoadFromIR(ctx *LoadContext, buildContext *build.Context, filename string, f *ir.File) error { - imp := newGoImporter(e.state, goImporterConfig{ - fset: ctx.Fset, - debugImports: ctx.DebugImports, - debugPrint: ctx.DebugPrint, - buildContext: buildContext, - }) - config := irLoaderConfig{ - state: e.state, - ctx: ctx, - importer: imp, - itab: typematch.NewImportsTab(stdinfo.PathByName), - gogrepFset: token.NewFileSet(), - } - l := newIRLoader(config) - rset, err := l.LoadFile(filename, f) - if err != nil { - return err - } - - if e.ruleSet == nil { - e.ruleSet = rset - } else { - combinedRuleSet, err := mergeRuleSets([]*goRuleSet{e.ruleSet, rset}) - if err != nil { - return err - } - e.ruleSet = combinedRuleSet - } - - return nil -} - -func (e *engine) Run(ctx *RunContext, buildContext *build.Context, f *ast.File) error { - if e.ruleSet == nil { - return errors.New("used Run() with an empty rule set; forgot to call Load() first?") - } - rset := e.ruleSet - return newRulesRunner(ctx, buildContext, e.state, rset).run(f) -} - -// engineState is a shared state inside the engine. -// Its access is synchronized, unlike the RunnerState which should be thread-local. -type engineState struct { - env *quasigo.Env - - typeByFQNMu sync.RWMutex - typeByFQN map[string]types.Type - - pkgCacheMu sync.RWMutex - // pkgCache contains all imported packages, from any importer. - pkgCache map[string]*types.Package -} - -func newEngineState() *engineState { - env := quasigo.NewEnv() - qstrings.ImportAll(env) - qstrconv.ImportAll(env) - qfmt.ImportAll(env) - state := &engineState{ - env: env, - pkgCache: make(map[string]*types.Package), - typeByFQN: map[string]types.Type{}, - } - for key, typ := range typeByName { - state.typeByFQN[key] = typ - } - initEnv(state, env) - return state -} - -func (state *engineState) GetCachedPackage(pkgPath string) *types.Package { - state.pkgCacheMu.RLock() - pkg := state.pkgCache[pkgPath] - state.pkgCacheMu.RUnlock() - return pkg -} - -func (state *engineState) AddCachedPackage(pkgPath string, pkg *types.Package) { - state.pkgCacheMu.Lock() - state.addCachedPackage(pkgPath, pkg) - state.pkgCacheMu.Unlock() -} - -func (state *engineState) addCachedPackage(pkgPath string, pkg *types.Package) { - state.pkgCache[pkgPath] = pkg - - // Also add all complete packages that are dependencies of the pkg. - // This way we cache more and avoid duplicated package loading - // which can lead to typechecking issues. - // - // Note that it does not increase our memory consumption - // as these packages are reachable via pkg, so they'll - // not be freed by GC anyway. - for _, imported := range pkg.Imports() { - if imported.Complete() { - state.addCachedPackage(imported.Path(), imported) - } - } -} - -func (state *engineState) FindType(importer *goImporter, currentPkg *types.Package, fqn string) (types.Type, error) { - // TODO(quasilyte): we can pre-populate the cache during the Load() phase. - // If we inspect the AST of a user function, all constant FQN can be preloaded. - // It could be a good thing as Load() is not expected to be executed in - // concurrent environment, so write-locking is not a big deal there. - - state.typeByFQNMu.RLock() - cachedType, ok := state.typeByFQN[fqn] - state.typeByFQNMu.RUnlock() - if ok { - return cachedType, nil - } - - // Code below is under a write critical section. - state.typeByFQNMu.Lock() - defer state.typeByFQNMu.Unlock() - - typ, err := state.findTypeNoCache(importer, currentPkg, fqn) - if err != nil { - return nil, err - } - state.typeByFQN[fqn] = typ - return typ, nil -} - -func (state *engineState) findTypeNoCache(importer *goImporter, currentPkg *types.Package, fqn string) (types.Type, error) { - pos := strings.LastIndexByte(fqn, '.') - if pos == -1 { - return nil, fmt.Errorf("%s is not a valid FQN", fqn) - } - pkgPath := fqn[:pos] - objectName := fqn[pos+1:] - var pkg *types.Package - if currentPkg != nil { - if directDep := findDependency(currentPkg, pkgPath); directDep != nil { - pkg = directDep - } - } - if pkg == nil { - loadedPkg, err := importer.Import(pkgPath) - if err != nil { - return nil, err - } - pkg = loadedPkg - } - obj := pkg.Scope().Lookup(objectName) - if obj == nil { - return nil, fmt.Errorf("%s is not found in %s", objectName, pkgPath) - } - typ := obj.Type() - state.typeByFQN[fqn] = typ - return typ, nil -} - -func inferBuildContext() *build.Context { - // Inherit most fields from the build.Default. - ctx := build.Default - - env, err := goenv.Read() - if err != nil { - return &ctx - } - - ctx.GOROOT = env["GOROOT"] - ctx.GOPATH = env["GOPATH"] - ctx.GOARCH = env["GOARCH"] - ctx.GOOS = env["GOOS"] - - switch os.Getenv("CGO_ENABLED") { - case "0": - ctx.CgoEnabled = false - case "1": - ctx.CgoEnabled = true - default: - ctx.CgoEnabled = env["CGO_ENABLED"] == "1" - } - - return &ctx -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go deleted file mode 100644 index 7320ab7fb..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go +++ /dev/null @@ -1,835 +0,0 @@ -package ruleguard - -import ( - "go/ast" - "go/constant" - "go/token" - "go/types" - "path/filepath" - - "github.com/quasilyte/gogrep" - "github.com/quasilyte/gogrep/nodetag" - "golang.org/x/tools/go/ast/astutil" - - "github.com/quasilyte/go-ruleguard/internal/xtypes" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/textmatch" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" -) - -const filterSuccess = matchFilterResult("") - -func filterFailure(reason string) matchFilterResult { - return matchFilterResult(reason) -} - -func asExprSlice(x ast.Node) *gogrep.NodeSlice { - if x, ok := x.(*gogrep.NodeSlice); ok && x.Kind == gogrep.ExprNodeSlice { - return x - } - return nil -} - -func exprListFilterApply(src string, list []ast.Expr, fn func(ast.Expr) bool) matchFilterResult { - for _, e := range list { - if !fn(e) { - return filterFailure(src) - } - } - return filterSuccess -} - -func makeNotFilter(src string, x matchFilter) filterFunc { - return func(params *filterParams) matchFilterResult { - if x.fn(params).Matched() { - return matchFilterResult(src) - } - return "" - } -} - -func makeAndFilter(lhs, rhs matchFilter) filterFunc { - return func(params *filterParams) matchFilterResult { - if lhsResult := lhs.fn(params); !lhsResult.Matched() { - return lhsResult - } - return rhs.fn(params) - } -} - -func makeOrFilter(lhs, rhs matchFilter) filterFunc { - return func(params *filterParams) matchFilterResult { - if lhsResult := lhs.fn(params); lhsResult.Matched() { - return filterSuccess - } - return rhs.fn(params) - } -} - -func makeDeadcodeFilter(src string) filterFunc { - return func(params *filterParams) matchFilterResult { - if params.deadcode { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeFileImportsFilter(src, pkgPath string) filterFunc { - return func(params *filterParams) matchFilterResult { - _, imported := params.imports[pkgPath] - if imported { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeFilePkgPathMatchesFilter(src string, re textmatch.Pattern) filterFunc { - return func(params *filterParams) matchFilterResult { - pkgPath := params.ctx.Pkg.Path() - if re.MatchString(pkgPath) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeFileNameMatchesFilter(src string, re textmatch.Pattern) filterFunc { - return func(params *filterParams) matchFilterResult { - if re.MatchString(filepath.Base(params.filename)) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makePureFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return isPure(params.ctx.Types, x) - }) - } - n := params.subExpr(varname) - if isPure(params.ctx.Types, n) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeConstFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return isConstant(params.ctx.Types, x) - }) - } - - n := params.subExpr(varname) - if isConstant(params.ctx.Types, n) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeConstSliceFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return isConstantSlice(params.ctx.Types, x) - }) - } - - n := params.subExpr(varname) - if isConstantSlice(params.ctx.Types, n) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeAddressableFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return isAddressable(params.ctx.Types, x) - }) - } - - n := params.subExpr(varname) - if isAddressable(params.ctx.Types, n) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeComparableFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return types.Comparable(params.typeofNode(x)) - }) - } - - if types.Comparable(params.typeofNode(params.subNode(varname))) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeVarContainsFilter(src, varname string, pat *gogrep.Pattern) filterFunc { - return func(params *filterParams) matchFilterResult { - params.gogrepSubState.CapturePreset = params.match.CaptureList() - matched := false - gogrep.Walk(params.subNode(varname), func(n ast.Node) bool { - if matched { - return false - } - pat.MatchNode(params.gogrepSubState, n, func(m gogrep.MatchData) { - matched = true - }) - return true - }) - if matched { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeCustomVarFilter(src, varname string, fn *quasigo.Func) filterFunc { - return func(params *filterParams) matchFilterResult { - // TODO(quasilyte): what if bytecode function panics due to the programming error? - // We should probably catch the panic here, print trace and return "false" - // from the filter (or even propagate that panic to let it crash). - params.varname = varname - result := quasigo.Call(params.env, fn) - if result.Value().(bool) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeImplementsFilter(src, varname string, iface *types.Interface) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return xtypes.Implements(params.typeofNode(x), iface) - }) - } - - typ := params.typeofNode(params.subExpr(varname)) - if xtypes.Implements(typ, iface) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeHasMethodFilter(src, varname string, fn *types.Func) filterFunc { - return func(params *filterParams) matchFilterResult { - typ := params.typeofNode(params.subNode(varname)) - if typeHasMethod(typ, fn) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeHasPointersFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - typ := params.typeofNode(params.subExpr(varname)) - if typeHasPointers(typ) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeIsIntUintFilter(src, varname string, underlying bool, kind types.BasicKind) filterFunc { - return func(params *filterParams) matchFilterResult { - typ := params.typeofNode(params.subExpr(varname)) - if underlying { - typ = typ.Underlying() - } - if basicType, ok := typ.(*types.Basic); ok { - first := kind - last := kind + 4 - if basicType.Kind() >= first && basicType.Kind() <= last { - return filterSuccess - } - } - return filterFailure(src) - } -} - -func makeTypeIsSignedFilter(src, varname string, underlying bool) filterFunc { - return func(params *filterParams) matchFilterResult { - typ := params.typeofNode(params.subExpr(varname)) - if underlying { - typ = typ.Underlying() - } - if basicType, ok := typ.(*types.Basic); ok { - if basicType.Info()&types.IsInteger != 0 && basicType.Info()&types.IsUnsigned == 0 { - return filterSuccess - } - } - return filterFailure(src) - } -} - -func makeTypeOfKindFilter(src, varname string, underlying bool, kind types.BasicInfo) filterFunc { - return func(params *filterParams) matchFilterResult { - typ := params.typeofNode(params.subExpr(varname)) - if underlying { - typ = typ.Underlying() - } - if basicType, ok := typ.(*types.Basic); ok { - if basicType.Info()&kind != 0 { - return filterSuccess - } - } - return filterFailure(src) - } -} - -func makeTypesIdenticalFilter(src, lhsVarname, rhsVarname string) filterFunc { - return func(params *filterParams) matchFilterResult { - lhsType := params.typeofNode(params.subNode(lhsVarname)) - rhsType := params.typeofNode(params.subNode(rhsVarname)) - if xtypes.Identical(lhsType, rhsType) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeRootSinkTypeIsFilter(src string, pat *typematch.Pattern) filterFunc { - return func(params *filterParams) matchFilterResult { - // TODO(quasilyte): add variadic support? - e, ok := params.match.Node().(ast.Expr) - if ok { - parent, kv := findSinkRoot(params) - typ := findSinkType(params, parent, kv, e) - if pat.MatchIdentical(params.typematchState, typ) { - return filterSuccess - } - } - return filterFailure(src) - } -} - -func makeTypeIsFilter(src, varname string, underlying bool, pat *typematch.Pattern) filterFunc { - if underlying { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return pat.MatchIdentical(params.typematchState, params.typeofNode(x).Underlying()) - }) - } - typ := params.typeofNode(params.subNode(varname)).Underlying() - if pat.MatchIdentical(params.typematchState, typ) { - return filterSuccess - } - return filterFailure(src) - } - } - - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return pat.MatchIdentical(params.typematchState, params.typeofNode(x)) - }) - } - typ := params.typeofNode(params.subNode(varname)) - if pat.MatchIdentical(params.typematchState, typ) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeConvertibleToFilter(src, varname string, dstType types.Type) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return types.ConvertibleTo(params.typeofNode(x), dstType) - }) - } - - typ := params.typeofNode(params.subExpr(varname)) - if types.ConvertibleTo(typ, dstType) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeAssignableToFilter(src, varname string, dstType types.Type) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - return types.AssignableTo(params.typeofNode(x), dstType) - }) - } - - typ := params.typeofNode(params.subExpr(varname)) - if types.AssignableTo(typ, dstType) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeLineFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - line1 := params.ctx.Fset.Position(params.subNode(varname).Pos()).Line - line2 := params.ctx.Fset.Position(params.subNode(rhsVarname).Pos()).Line - lhsValue := constant.MakeInt64(int64(line1)) - rhsValue := constant.MakeInt64(int64(line2)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeObjectIsVariadicParamFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - if params.currentFunc == nil { - return filterFailure(src) - } - funcObj, ok := params.ctx.Types.ObjectOf(params.currentFunc.Name).(*types.Func) - if !ok { - return filterFailure(src) - } - funcSig := funcObj.Type().(*types.Signature) - if !funcSig.Variadic() { - return filterFailure(src) - } - paramObj := funcSig.Params().At(funcSig.Params().Len() - 1) - obj := params.ctx.Types.ObjectOf(identOf(params.subExpr(varname))) - if paramObj != obj { - return filterFailure(src) - } - return filterSuccess - } -} - -func makeObjectIsGlobalFilter(src, varname string) filterFunc { - return func(params *filterParams) matchFilterResult { - obj := params.ctx.Types.ObjectOf(identOf(params.subExpr(varname))) - globalScope := params.ctx.Pkg.Scope() - if obj.Parent() == globalScope { - return filterSuccess - } - - return filterFailure(src) - } -} - -func makeGoVersionFilter(src string, op token.Token, version GoVersion) filterFunc { - return func(params *filterParams) matchFilterResult { - if params.ctx.GoVersion.IsAny() { - return filterSuccess - } - if versionCompare(params.ctx.GoVersion, op, version) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeLineConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - n := params.subNode(varname) - lhsValue := constant.MakeInt64(int64(params.ctx.Fset.Position(n.Pos()).Line)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeSizeConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - typ := params.typeofNode(x) - if isTypeParam(typ) { - return false - } - lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(typ)) - return constant.Compare(lhsValue, op, rhsValue) - }) - } - - typ := params.typeofNode(params.subExpr(varname)) - if isTypeParam(typ) { - return filterFailure(src) - } - lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(typ)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTypeSizeFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { - return func(params *filterParams) matchFilterResult { - lhsTyp := params.typeofNode(params.subExpr(varname)) - rhsTyp := params.typeofNode(params.subExpr(rhsVarname)) - if isTypeParam(lhsTyp) || isTypeParam(rhsTyp) { - return filterFailure(src) - } - lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(lhsTyp)) - rhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(rhsTyp)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeValueIntConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - lhsValue := intValueOf(params.ctx.Types, x) - return lhsValue != nil && constant.Compare(lhsValue, op, rhsValue) - }) - } - - lhsValue := intValueOf(params.ctx.Types, params.subExpr(varname)) - if lhsValue == nil { - return filterFailure(src) // The value is unknown - } - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeValueIntFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - lhsValue := intValueOf(params.ctx.Types, params.subExpr(varname)) - if lhsValue == nil { - return filterFailure(src) - } - rhsValue := intValueOf(params.ctx.Types, params.subExpr(rhsVarname)) - if rhsValue == nil { - return filterFailure(src) - } - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTextConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - s := params.nodeText(params.subNode(varname)) - lhsValue := constant.MakeString(string(s)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTextFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - s1 := params.nodeText(params.subNode(varname)) - lhsValue := constant.MakeString(string(s1)) - n, _ := params.match.CapturedByName(rhsVarname) - s2 := params.nodeText(n) - rhsValue := constant.MakeString(string(s2)) - if constant.Compare(lhsValue, op, rhsValue) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeTextMatchesFilter(src, varname string, re textmatch.Pattern) filterFunc { - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - if re.Match(params.nodeText(params.subNode(varname))) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeRootParentNodeIsFilter(src string, tag nodetag.Value) filterFunc { - return func(params *filterParams) matchFilterResult { - parent := params.nodePath.Parent() - if nodeIs(parent, tag) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeNodeIsFilter(src, varname string, tag nodetag.Value) filterFunc { - // TODO(quasilyte): add comment nodes support? - // TODO(quasilyte): add variadic support. - return func(params *filterParams) matchFilterResult { - n := params.subNode(varname) - if nodeIs(n, tag) { - return filterSuccess - } - return filterFailure(src) - } -} - -func makeObjectIsFilter(src, varname, objectName string) filterFunc { - var predicate func(types.Object) bool - switch objectName { - case "Func": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Func) - return ok - } - case "Var": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Var) - return ok - } - case "Const": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Const) - return ok - } - case "TypeName": - predicate = func(x types.Object) bool { - _, ok := x.(*types.TypeName) - return ok - } - case "Label": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Label) - return ok - } - case "PkgName": - predicate = func(x types.Object) bool { - _, ok := x.(*types.PkgName) - return ok - } - case "Builtin": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Builtin) - return ok - } - case "Nil": - predicate = func(x types.Object) bool { - _, ok := x.(*types.Nil) - return ok - } - } - - return func(params *filterParams) matchFilterResult { - if list := asExprSlice(params.subNode(varname)); list != nil { - return exprListFilterApply(src, list.GetExprSlice(), func(x ast.Expr) bool { - ident := identOf(x) - return ident != nil && predicate(params.ctx.Types.ObjectOf(ident)) - }) - } - - ident := identOf(params.subExpr(varname)) - if ident == nil { - return filterFailure(src) - } - object := params.ctx.Types.ObjectOf(ident) - if predicate(object) { - return filterSuccess - } - return filterFailure(src) - } -} - -func nodeIs(n ast.Node, tag nodetag.Value) bool { - var matched bool - switch tag { - case nodetag.Expr: - _, matched = n.(ast.Expr) - case nodetag.Stmt: - _, matched = n.(ast.Stmt) - case nodetag.Node: - matched = true - default: - matched = (tag == nodetag.FromNode(n)) - } - return matched -} - -func typeHasMethod(typ types.Type, fn *types.Func) bool { - obj, _, _ := types.LookupFieldOrMethod(typ, true, fn.Pkg(), fn.Name()) - fn2, ok := obj.(*types.Func) - if !ok { - return false - } - return xtypes.Identical(fn.Type(), fn2.Type()) -} - -func typeHasPointers(typ types.Type) bool { - switch typ := typ.(type) { - case *types.Basic: - switch typ.Kind() { - case types.UnsafePointer, types.String, types.UntypedNil, types.UntypedString: - return true - } - return false - - case *types.Named: - return typeHasPointers(typ.Underlying()) - - case *types.Struct: - for i := 0; i < typ.NumFields(); i++ { - if typeHasPointers(typ.Field(i).Type()) { - return true - } - } - return false - - case *types.Array: - return typeHasPointers(typ.Elem()) - - default: - return true - } -} - -func findSinkRoot(params *filterParams) (ast.Node, *ast.KeyValueExpr) { - for i := 1; i < params.nodePath.Len(); i++ { - switch n := params.nodePath.NthParent(i).(type) { - case *ast.ParenExpr: - // Skip and continue. - continue - case *ast.KeyValueExpr: - return params.nodePath.NthParent(i + 1).(ast.Expr), n - default: - return n, nil - } - } - return nil, nil -} - -func findContainingFunc(params *filterParams) *types.Signature { - for i := 2; i < params.nodePath.Len(); i++ { - switch n := params.nodePath.NthParent(i).(type) { - case *ast.FuncDecl: - fn, ok := params.ctx.Types.TypeOf(n.Name).(*types.Signature) - if ok { - return fn - } - case *ast.FuncLit: - fn, ok := params.ctx.Types.TypeOf(n.Type).(*types.Signature) - if ok { - return fn - } - } - } - return nil -} - -func findSinkType(params *filterParams, parent ast.Node, kv *ast.KeyValueExpr, e ast.Expr) types.Type { - switch parent := parent.(type) { - case *ast.ValueSpec: - return params.ctx.Types.TypeOf(parent.Type) - - case *ast.ReturnStmt: - for i, result := range parent.Results { - if astutil.Unparen(result) != e { - continue - } - sig := findContainingFunc(params) - if sig == nil { - break - } - return sig.Results().At(i).Type() - } - - case *ast.IndexExpr: - if astutil.Unparen(parent.Index) == e { - switch typ := params.ctx.Types.TypeOf(parent.X).Underlying().(type) { - case *types.Map: - return typ.Key() - case *types.Slice, *types.Array: - return nil // TODO: some untyped int type? - } - } - - case *ast.AssignStmt: - if parent.Tok != token.ASSIGN || len(parent.Lhs) != len(parent.Rhs) { - break - } - for i, rhs := range parent.Rhs { - if rhs == e { - return params.ctx.Types.TypeOf(parent.Lhs[i]) - } - } - - case *ast.CompositeLit: - switch typ := params.ctx.Types.TypeOf(parent).Underlying().(type) { - case *types.Slice: - return typ.Elem() - case *types.Array: - return typ.Elem() - case *types.Map: - if astutil.Unparen(kv.Key) == e { - return typ.Key() - } - return typ.Elem() - case *types.Struct: - fieldName, ok := kv.Key.(*ast.Ident) - if !ok { - break - } - for i := 0; i < typ.NumFields(); i++ { - field := typ.Field(i) - if field.Name() == fieldName.String() { - return field.Type() - } - } - } - - case *ast.CallExpr: - switch typ := params.ctx.Types.TypeOf(parent.Fun).(type) { - case *types.Signature: - // A function call argument. - for i, arg := range parent.Args { - if astutil.Unparen(arg) != e { - continue - } - isVariadicArg := (i >= typ.Params().Len()-1) && typ.Variadic() - if isVariadicArg && !parent.Ellipsis.IsValid() { - return typ.Params().At(typ.Params().Len() - 1).Type().(*types.Slice).Elem() - } - if i < typ.Params().Len() { - return typ.Params().At(i).Type() - } - break - } - default: - // Probably a type cast. - return typ - } - } - - return invalidType -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go deleted file mode 100644 index 39e4a492d..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go +++ /dev/null @@ -1,58 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/token" - "strconv" - "strings" -) - -type GoVersion struct { - Major int - Minor int -} - -func (ver GoVersion) IsAny() bool { return ver.Major == 0 } - -func ParseGoVersion(version string) (GoVersion, error) { - var result GoVersion - if version == "" { - return GoVersion{}, nil - } - parts := strings.Split(version, ".") - if len(parts) != 2 { - return result, fmt.Errorf("invalid format: %s", version) - } - major, err := strconv.Atoi(parts[0]) - if err != nil { - return result, fmt.Errorf("invalid major version part: %s: %s", parts[0], err) - } - minor, err := strconv.Atoi(parts[1]) - if err != nil { - return result, fmt.Errorf("invalid minor version part: %s: %s", parts[1], err) - } - result.Major = major - result.Minor = minor - return result, nil -} - -func versionCompare(x GoVersion, op token.Token, y GoVersion) bool { - switch op { - case token.EQL: // == - return x.Major == y.Major && x.Minor == y.Minor - case token.NEQ: // != - return !versionCompare(x, token.EQL, y) - - case token.GTR: // > - return x.Major > y.Major || (x.Major == y.Major && x.Minor > y.Minor) - case token.GEQ: // >= - return x.Major > y.Major || (x.Major == y.Major && x.Minor >= y.Minor) - case token.LSS: // < - return x.Major < y.Major || (x.Major == y.Major && x.Minor < y.Minor) - case token.LEQ: // <= - return x.Major < y.Major || (x.Major == y.Major && x.Minor <= y.Minor) - - default: - panic("unexpected version compare op") - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go deleted file mode 100644 index 655fc5b89..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go +++ /dev/null @@ -1,154 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/ast" - "go/types" - "regexp" - - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" - "github.com/quasilyte/gogrep" - "github.com/quasilyte/gogrep/nodetag" -) - -type goRuleSet struct { - universal *scopedGoRuleSet - - groups map[string]*GoRuleGroup // To handle redefinitions -} - -type scopedGoRuleSet struct { - categorizedNum int - rulesByTag [nodetag.NumBuckets][]goRule - commentRules []goCommentRule -} - -type goCommentRule struct { - base goRule - pat *regexp.Regexp - captureGroups bool -} - -type goRule struct { - group *GoRuleGroup - line int - pat *gogrep.Pattern - msg string - location string - suggestion string - filter matchFilter - do *quasigo.Func -} - -type matchFilterResult string - -func (s matchFilterResult) Matched() bool { return s == "" } - -func (s matchFilterResult) RejectReason() string { return string(s) } - -type filterFunc func(*filterParams) matchFilterResult - -type matchFilter struct { - src string - fn func(*filterParams) matchFilterResult -} - -type filterParams struct { - ctx *RunContext - filename string - imports map[string]struct{} - env *quasigo.EvalEnv - - importer *goImporter - gogrepSubState *gogrep.MatcherState - typematchState *typematch.MatcherState - - match matchData - nodePath *nodePath - - nodeText func(n ast.Node) []byte - nodeString func(n ast.Node) string - - deadcode bool - - currentFunc *ast.FuncDecl - - // varname is set only for custom filters before bytecode function is called. - varname string - - // Both of these are Do() function related fields. - reportString string - suggestString string -} - -func (params *filterParams) subNode(name string) ast.Node { - n, _ := params.match.CapturedByName(name) - return n -} - -func (params *filterParams) subExpr(name string) ast.Expr { - n, _ := params.match.CapturedByName(name) - switch n := n.(type) { - case ast.Expr: - return n - case *ast.ExprStmt: - return n.X - default: - return nil - } -} - -func (params *filterParams) typeofNode(n ast.Node) types.Type { - var e ast.Expr - switch n := n.(type) { - case ast.Expr: - e = n - case *ast.Field: - e = n.Type - } - if typ := params.ctx.Types.TypeOf(e); typ != nil { - return typ - } - return invalidType -} - -func mergeRuleSets(toMerge []*goRuleSet) (*goRuleSet, error) { - out := &goRuleSet{ - universal: &scopedGoRuleSet{}, - groups: make(map[string]*GoRuleGroup), - } - - for _, x := range toMerge { - out.universal = appendScopedRuleSet(out.universal, x.universal) - for groupName, group := range x.groups { - if prevGroup, ok := out.groups[groupName]; ok { - newRef := fmt.Sprintf("%s:%d", group.Filename, group.Line) - oldRef := fmt.Sprintf("%s:%d", prevGroup.Filename, prevGroup.Line) - return nil, fmt.Errorf("%s: redefinition of %s(), previously defined at %s", newRef, groupName, oldRef) - } - out.groups[groupName] = group - } - } - - return out, nil -} - -func appendScopedRuleSet(dst, src *scopedGoRuleSet) *scopedGoRuleSet { - for tag, rules := range src.rulesByTag { - dst.rulesByTag[tag] = append(dst.rulesByTag[tag], cloneRuleSlice(rules)...) - dst.categorizedNum += len(rules) - } - dst.commentRules = append(dst.commentRules, src.commentRules...) - return dst -} - -func cloneRuleSlice(slice []goRule) []goRule { - out := make([]goRule, len(slice)) - for i, rule := range slice { - clone := rule - clone.pat = rule.pat.Clone() - out[i] = clone - } - return out -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go deleted file mode 100644 index 3f35b17e1..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go +++ /dev/null @@ -1,67 +0,0 @@ -package goutil - -import ( - "fmt" - "go/ast" - "go/importer" - "go/parser" - "go/printer" - "go/token" - "go/types" - "strings" -) - -// SprintNode returns the textual representation of n. -// If fset is nil, freshly created file set will be used. -func SprintNode(fset *token.FileSet, n ast.Node) string { - if fset == nil { - fset = token.NewFileSet() - } - var buf strings.Builder - if err := printer.Fprint(&buf, fset, n); err != nil { - return "" - } - return buf.String() -} - -type LoadConfig struct { - Fset *token.FileSet - Filename string - Data interface{} - Importer types.Importer -} - -type LoadResult struct { - Pkg *types.Package - Types *types.Info - Syntax *ast.File -} - -func LoadGoFile(config LoadConfig) (*LoadResult, error) { - imp := config.Importer - if imp == nil { - imp = importer.ForCompiler(config.Fset, "source", nil) - } - - parserFlags := parser.ParseComments - f, err := parser.ParseFile(config.Fset, config.Filename, config.Data, parserFlags) - if err != nil { - return nil, fmt.Errorf("parse file error: %w", err) - } - typechecker := types.Config{Importer: imp} - typesInfo := &types.Info{ - Types: map[ast.Expr]types.TypeAndValue{}, - Uses: map[*ast.Ident]types.Object{}, - Defs: map[*ast.Ident]types.Object{}, - } - pkg, err := typechecker.Check(f.Name.String(), config.Fset, []*ast.File{f}, typesInfo) - if err != nil { - return nil, fmt.Errorf("typechecker error: %w", err) - } - result := &LoadResult{ - Pkg: pkg, - Types: typesInfo, - Syntax: f, - } - return result, nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/resolve.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/resolve.go deleted file mode 100644 index 8705707ac..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/resolve.go +++ /dev/null @@ -1,33 +0,0 @@ -package goutil - -import ( - "go/ast" - "go/types" - - "golang.org/x/tools/go/ast/astutil" -) - -func ResolveFunc(info *types.Info, callable ast.Expr) (ast.Expr, *types.Func) { - switch callable := astutil.Unparen(callable).(type) { - case *ast.Ident: - sig, ok := info.ObjectOf(callable).(*types.Func) - if !ok { - return nil, nil - } - return nil, sig - - case *ast.SelectorExpr: - sig, ok := info.ObjectOf(callable.Sel).(*types.Func) - if !ok { - return nil, nil - } - isMethod := sig.Type().(*types.Signature).Recv() != nil - if _, ok := callable.X.(*ast.Ident); ok && !isMethod { - return nil, sig - } - return callable.X, sig - - default: - return nil, nil - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go deleted file mode 100644 index 19494db9c..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go +++ /dev/null @@ -1,95 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/build" - "go/importer" - "go/token" - "go/types" - "runtime" - - "github.com/quasilyte/go-ruleguard/internal/xsrcimporter" -) - -// goImporter is a `types.Importer` that tries to load a package no matter what. -// It iterates through multiple import strategies and accepts whatever succeeds first. -type goImporter struct { - // TODO(quasilyte): share importers with gogrep? - - state *engineState - - defaultImporter types.Importer - srcImporter types.Importer - - fset *token.FileSet - buildContext *build.Context - - debugImports bool - debugPrint func(string) -} - -type goImporterConfig struct { - fset *token.FileSet - debugImports bool - debugPrint func(string) - buildContext *build.Context -} - -func newGoImporter(state *engineState, config goImporterConfig) *goImporter { - imp := &goImporter{ - state: state, - fset: config.fset, - debugImports: config.debugImports, - debugPrint: config.debugPrint, - defaultImporter: importer.Default(), - buildContext: config.buildContext, - } - imp.initSourceImporter() - return imp -} - -func (imp *goImporter) Import(path string) (*types.Package, error) { - if pkg := imp.state.GetCachedPackage(path); pkg != nil { - if imp.debugImports { - imp.debugPrint(fmt.Sprintf(`imported "%s" from importer cache`, path)) - } - return pkg, nil - } - - pkg, srcErr := imp.srcImporter.Import(path) - if srcErr == nil { - imp.state.AddCachedPackage(path, pkg) - if imp.debugImports { - imp.debugPrint(fmt.Sprintf(`imported "%s" from source importer`, path)) - } - return pkg, nil - } - - pkg, defaultErr := imp.defaultImporter.Import(path) - if defaultErr == nil { - imp.state.AddCachedPackage(path, pkg) - if imp.debugImports { - imp.debugPrint(fmt.Sprintf(`imported "%s" from %s importer`, path, runtime.Compiler)) - } - return pkg, nil - } - - if imp.debugImports { - imp.debugPrint(fmt.Sprintf(`failed to import "%s":`, path)) - imp.debugPrint(fmt.Sprintf(" %s importer: %v", runtime.Compiler, defaultErr)) - imp.debugPrint(fmt.Sprintf(" source importer: %v", srcErr)) - imp.debugPrint(fmt.Sprintf(" GOROOT=%q GOPATH=%q", imp.buildContext.GOROOT, imp.buildContext.GOPATH)) - } - - return nil, defaultErr -} - -func (imp *goImporter) initSourceImporter() { - if imp.buildContext == nil { - if imp.debugImports { - imp.debugPrint("using build.Default context") - } - imp.buildContext = &build.Default - } - imp.srcImporter = xsrcimporter.New(imp.buildContext, imp.fset) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go deleted file mode 100644 index bc2a5ee5b..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go +++ /dev/null @@ -1,282 +0,0 @@ -// Code generated "gen_filter_op.go"; DO NOT EDIT. - -package ir - -const ( - FilterInvalidOp FilterOp = 0 - - // !$Args[0] - FilterNotOp FilterOp = 1 - - // $Args[0] && $Args[1] - FilterAndOp FilterOp = 2 - - // $Args[0] || $Args[1] - FilterOrOp FilterOp = 3 - - // $Args[0] == $Args[1] - FilterEqOp FilterOp = 4 - - // $Args[0] != $Args[1] - FilterNeqOp FilterOp = 5 - - // $Args[0] > $Args[1] - FilterGtOp FilterOp = 6 - - // $Args[0] < $Args[1] - FilterLtOp FilterOp = 7 - - // $Args[0] >= $Args[1] - FilterGtEqOp FilterOp = 8 - - // $Args[0] <= $Args[1] - FilterLtEqOp FilterOp = 9 - - // m[$Value].Addressable - // $Value type: string - FilterVarAddressableOp FilterOp = 10 - - // m[$Value].Comparable - // $Value type: string - FilterVarComparableOp FilterOp = 11 - - // m[$Value].Pure - // $Value type: string - FilterVarPureOp FilterOp = 12 - - // m[$Value].Const - // $Value type: string - FilterVarConstOp FilterOp = 13 - - // m[$Value].ConstSlice - // $Value type: string - FilterVarConstSliceOp FilterOp = 14 - - // m[$Value].Text - // $Value type: string - FilterVarTextOp FilterOp = 15 - - // m[$Value].Line - // $Value type: string - FilterVarLineOp FilterOp = 16 - - // m[$Value].Value.Int() - // $Value type: string - FilterVarValueIntOp FilterOp = 17 - - // m[$Value].Type.Size - // $Value type: string - FilterVarTypeSizeOp FilterOp = 18 - - // m[$Value].Type.HasPointers() - // $Value type: string - FilterVarTypeHasPointersOp FilterOp = 19 - - // m[$Value].Filter($Args[0]) - // $Value type: string - FilterVarFilterOp FilterOp = 20 - - // m[$Value].Node.Is($Args[0]) - // $Value type: string - FilterVarNodeIsOp FilterOp = 21 - - // m[$Value].Object.Is($Args[0]) - // $Value type: string - FilterVarObjectIsOp FilterOp = 22 - - // m[$Value].Object.IsGlobal() - // $Value type: string - FilterVarObjectIsGlobalOp FilterOp = 23 - - // m[$Value].Object.IsVariadicParam() - // $Value type: string - FilterVarObjectIsVariadicParamOp FilterOp = 24 - - // m[$Value].Type.Is($Args[0]) - // $Value type: string - FilterVarTypeIsOp FilterOp = 25 - - // m[$Value].Type.IdenticalTo($Args[0]) - // $Value type: string - FilterVarTypeIdenticalToOp FilterOp = 26 - - // m[$Value].Type.Underlying().Is($Args[0]) - // $Value type: string - FilterVarTypeUnderlyingIsOp FilterOp = 27 - - // m[$Value].Type.OfKind($Args[0]) - // $Value type: string - FilterVarTypeOfKindOp FilterOp = 28 - - // m[$Value].Type.Underlying().OfKind($Args[0]) - // $Value type: string - FilterVarTypeUnderlyingOfKindOp FilterOp = 29 - - // m[$Value].Type.ConvertibleTo($Args[0]) - // $Value type: string - FilterVarTypeConvertibleToOp FilterOp = 30 - - // m[$Value].Type.AssignableTo($Args[0]) - // $Value type: string - FilterVarTypeAssignableToOp FilterOp = 31 - - // m[$Value].Type.Implements($Args[0]) - // $Value type: string - FilterVarTypeImplementsOp FilterOp = 32 - - // m[$Value].Type.HasMethod($Args[0]) - // $Value type: string - FilterVarTypeHasMethodOp FilterOp = 33 - - // m[$Value].Text.Matches($Args[0]) - // $Value type: string - FilterVarTextMatchesOp FilterOp = 34 - - // m[$Value].Contains($Args[0]) - // $Value type: string - FilterVarContainsOp FilterOp = 35 - - // m.Deadcode() - FilterDeadcodeOp FilterOp = 36 - - // m.GoVersion().Eq($Value) - // $Value type: string - FilterGoVersionEqOp FilterOp = 37 - - // m.GoVersion().LessThan($Value) - // $Value type: string - FilterGoVersionLessThanOp FilterOp = 38 - - // m.GoVersion().GreaterThan($Value) - // $Value type: string - FilterGoVersionGreaterThanOp FilterOp = 39 - - // m.GoVersion().LessEqThan($Value) - // $Value type: string - FilterGoVersionLessEqThanOp FilterOp = 40 - - // m.GoVersion().GreaterEqThan($Value) - // $Value type: string - FilterGoVersionGreaterEqThanOp FilterOp = 41 - - // m.File.Imports($Value) - // $Value type: string - FilterFileImportsOp FilterOp = 42 - - // m.File.PkgPath.Matches($Value) - // $Value type: string - FilterFilePkgPathMatchesOp FilterOp = 43 - - // m.File.Name.Matches($Value) - // $Value type: string - FilterFileNameMatchesOp FilterOp = 44 - - // $Value holds a function name - // $Value type: string - FilterFilterFuncRefOp FilterOp = 45 - - // $Value holds a string constant - // $Value type: string - FilterStringOp FilterOp = 46 - - // $Value holds an int64 constant - // $Value type: int64 - FilterIntOp FilterOp = 47 - - // m[`$$`].Node.Parent().Is($Args[0]) - FilterRootNodeParentIsOp FilterOp = 48 - - // m[`$$`].SinkType.Is($Args[0]) - FilterRootSinkTypeIsOp FilterOp = 49 -) - -var filterOpNames = map[FilterOp]string{ - FilterInvalidOp: `Invalid`, - FilterNotOp: `Not`, - FilterAndOp: `And`, - FilterOrOp: `Or`, - FilterEqOp: `Eq`, - FilterNeqOp: `Neq`, - FilterGtOp: `Gt`, - FilterLtOp: `Lt`, - FilterGtEqOp: `GtEq`, - FilterLtEqOp: `LtEq`, - FilterVarAddressableOp: `VarAddressable`, - FilterVarComparableOp: `VarComparable`, - FilterVarPureOp: `VarPure`, - FilterVarConstOp: `VarConst`, - FilterVarConstSliceOp: `VarConstSlice`, - FilterVarTextOp: `VarText`, - FilterVarLineOp: `VarLine`, - FilterVarValueIntOp: `VarValueInt`, - FilterVarTypeSizeOp: `VarTypeSize`, - FilterVarTypeHasPointersOp: `VarTypeHasPointers`, - FilterVarFilterOp: `VarFilter`, - FilterVarNodeIsOp: `VarNodeIs`, - FilterVarObjectIsOp: `VarObjectIs`, - FilterVarObjectIsGlobalOp: `VarObjectIsGlobal`, - FilterVarObjectIsVariadicParamOp: `VarObjectIsVariadicParam`, - FilterVarTypeIsOp: `VarTypeIs`, - FilterVarTypeIdenticalToOp: `VarTypeIdenticalTo`, - FilterVarTypeUnderlyingIsOp: `VarTypeUnderlyingIs`, - FilterVarTypeOfKindOp: `VarTypeOfKind`, - FilterVarTypeUnderlyingOfKindOp: `VarTypeUnderlyingOfKind`, - FilterVarTypeConvertibleToOp: `VarTypeConvertibleTo`, - FilterVarTypeAssignableToOp: `VarTypeAssignableTo`, - FilterVarTypeImplementsOp: `VarTypeImplements`, - FilterVarTypeHasMethodOp: `VarTypeHasMethod`, - FilterVarTextMatchesOp: `VarTextMatches`, - FilterVarContainsOp: `VarContains`, - FilterDeadcodeOp: `Deadcode`, - FilterGoVersionEqOp: `GoVersionEq`, - FilterGoVersionLessThanOp: `GoVersionLessThan`, - FilterGoVersionGreaterThanOp: `GoVersionGreaterThan`, - FilterGoVersionLessEqThanOp: `GoVersionLessEqThan`, - FilterGoVersionGreaterEqThanOp: `GoVersionGreaterEqThan`, - FilterFileImportsOp: `FileImports`, - FilterFilePkgPathMatchesOp: `FilePkgPathMatches`, - FilterFileNameMatchesOp: `FileNameMatches`, - FilterFilterFuncRefOp: `FilterFuncRef`, - FilterStringOp: `String`, - FilterIntOp: `Int`, - FilterRootNodeParentIsOp: `RootNodeParentIs`, - FilterRootSinkTypeIsOp: `RootSinkTypeIs`, -} -var filterOpFlags = map[FilterOp]uint64{ - FilterAndOp: flagIsBinaryExpr, - FilterOrOp: flagIsBinaryExpr, - FilterEqOp: flagIsBinaryExpr, - FilterNeqOp: flagIsBinaryExpr, - FilterGtOp: flagIsBinaryExpr, - FilterLtOp: flagIsBinaryExpr, - FilterGtEqOp: flagIsBinaryExpr, - FilterLtEqOp: flagIsBinaryExpr, - FilterVarAddressableOp: flagHasVar, - FilterVarComparableOp: flagHasVar, - FilterVarPureOp: flagHasVar, - FilterVarConstOp: flagHasVar, - FilterVarConstSliceOp: flagHasVar, - FilterVarTextOp: flagHasVar, - FilterVarLineOp: flagHasVar, - FilterVarValueIntOp: flagHasVar, - FilterVarTypeSizeOp: flagHasVar, - FilterVarTypeHasPointersOp: flagHasVar, - FilterVarFilterOp: flagHasVar, - FilterVarNodeIsOp: flagHasVar, - FilterVarObjectIsOp: flagHasVar, - FilterVarObjectIsGlobalOp: flagHasVar, - FilterVarObjectIsVariadicParamOp: flagHasVar, - FilterVarTypeIsOp: flagHasVar, - FilterVarTypeIdenticalToOp: flagHasVar, - FilterVarTypeUnderlyingIsOp: flagHasVar, - FilterVarTypeOfKindOp: flagHasVar, - FilterVarTypeUnderlyingOfKindOp: flagHasVar, - FilterVarTypeConvertibleToOp: flagHasVar, - FilterVarTypeAssignableToOp: flagHasVar, - FilterVarTypeImplementsOp: flagHasVar, - FilterVarTypeHasMethodOp: flagHasVar, - FilterVarTextMatchesOp: flagHasVar, - FilterVarContainsOp: flagHasVar, - FilterStringOp: flagIsBasicLit, - FilterIntOp: flagIsBasicLit, -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go deleted file mode 100644 index b1c819492..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go +++ /dev/null @@ -1,148 +0,0 @@ -//go:build generate -// +build generate - -package main - -import ( - "bytes" - "fmt" - "go/format" - "os" - "strings" -) - -type opInfo struct { - name string - comment string - valueType string - flags uint64 -} - -const ( - flagIsBinaryExpr uint64 = 1 << iota - flagIsBasicLit - flagHasVar -) - -func main() { - ops := []opInfo{ - {name: "Invalid"}, - - {name: "Not", comment: "!$Args[0]"}, - - // Binary expressions. - {name: "And", comment: "$Args[0] && $Args[1]", flags: flagIsBinaryExpr}, - {name: "Or", comment: "$Args[0] || $Args[1]", flags: flagIsBinaryExpr}, - {name: "Eq", comment: "$Args[0] == $Args[1]", flags: flagIsBinaryExpr}, - {name: "Neq", comment: "$Args[0] != $Args[1]", flags: flagIsBinaryExpr}, - {name: "Gt", comment: "$Args[0] > $Args[1]", flags: flagIsBinaryExpr}, - {name: "Lt", comment: "$Args[0] < $Args[1]", flags: flagIsBinaryExpr}, - {name: "GtEq", comment: "$Args[0] >= $Args[1]", flags: flagIsBinaryExpr}, - {name: "LtEq", comment: "$Args[0] <= $Args[1]", flags: flagIsBinaryExpr}, - - {name: "VarAddressable", comment: "m[$Value].Addressable", valueType: "string", flags: flagHasVar}, - {name: "VarComparable", comment: "m[$Value].Comparable", valueType: "string", flags: flagHasVar}, - {name: "VarPure", comment: "m[$Value].Pure", valueType: "string", flags: flagHasVar}, - {name: "VarConst", comment: "m[$Value].Const", valueType: "string", flags: flagHasVar}, - {name: "VarConstSlice", comment: "m[$Value].ConstSlice", valueType: "string", flags: flagHasVar}, - {name: "VarText", comment: "m[$Value].Text", valueType: "string", flags: flagHasVar}, - {name: "VarLine", comment: "m[$Value].Line", valueType: "string", flags: flagHasVar}, - {name: "VarValueInt", comment: "m[$Value].Value.Int()", valueType: "string", flags: flagHasVar}, - {name: "VarTypeSize", comment: "m[$Value].Type.Size", valueType: "string", flags: flagHasVar}, - {name: "VarTypeHasPointers", comment: "m[$Value].Type.HasPointers()", valueType: "string", flags: flagHasVar}, - - {name: "VarFilter", comment: "m[$Value].Filter($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarNodeIs", comment: "m[$Value].Node.Is($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarObjectIs", comment: "m[$Value].Object.Is($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarObjectIsGlobal", comment: "m[$Value].Object.IsGlobal()", valueType: "string", flags: flagHasVar}, - {name: "VarObjectIsVariadicParam", comment: "m[$Value].Object.IsVariadicParam()", valueType: "string", flags: flagHasVar}, - {name: "VarTypeIs", comment: "m[$Value].Type.Is($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeIdenticalTo", comment: "m[$Value].Type.IdenticalTo($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeUnderlyingIs", comment: "m[$Value].Type.Underlying().Is($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeOfKind", comment: "m[$Value].Type.OfKind($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeUnderlyingOfKind", comment: "m[$Value].Type.Underlying().OfKind($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeConvertibleTo", comment: "m[$Value].Type.ConvertibleTo($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeAssignableTo", comment: "m[$Value].Type.AssignableTo($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeImplements", comment: "m[$Value].Type.Implements($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTypeHasMethod", comment: "m[$Value].Type.HasMethod($Args[0])", valueType: "string", flags: flagHasVar}, - {name: "VarTextMatches", comment: "m[$Value].Text.Matches($Args[0])", valueType: "string", flags: flagHasVar}, - - {name: "VarContains", comment: "m[$Value].Contains($Args[0])", valueType: "string", flags: flagHasVar}, - - {name: "Deadcode", comment: "m.Deadcode()"}, - - {name: "GoVersionEq", comment: "m.GoVersion().Eq($Value)", valueType: "string"}, - {name: "GoVersionLessThan", comment: "m.GoVersion().LessThan($Value)", valueType: "string"}, - {name: "GoVersionGreaterThan", comment: "m.GoVersion().GreaterThan($Value)", valueType: "string"}, - {name: "GoVersionLessEqThan", comment: "m.GoVersion().LessEqThan($Value)", valueType: "string"}, - {name: "GoVersionGreaterEqThan", comment: "m.GoVersion().GreaterEqThan($Value)", valueType: "string"}, - - {name: "FileImports", comment: "m.File.Imports($Value)", valueType: "string"}, - {name: "FilePkgPathMatches", comment: "m.File.PkgPath.Matches($Value)", valueType: "string"}, - {name: "FileNameMatches", comment: "m.File.Name.Matches($Value)", valueType: "string"}, - - {name: "FilterFuncRef", comment: "$Value holds a function name", valueType: "string"}, - - {name: "String", comment: "$Value holds a string constant", valueType: "string", flags: flagIsBasicLit}, - {name: "Int", comment: "$Value holds an int64 constant", valueType: "int64", flags: flagIsBasicLit}, - - {name: "RootNodeParentIs", comment: "m[`$$`].Node.Parent().Is($Args[0])"}, - {name: "RootSinkTypeIs", comment: "m[`$$`].SinkType.Is($Args[0])"}, - } - - var buf bytes.Buffer - - buf.WriteString(`// Code generated "gen_filter_op.go"; DO NOT EDIT.` + "\n") - buf.WriteString("\n") - buf.WriteString("package ir\n") - buf.WriteString("const (\n") - - for i, op := range ops { - if strings.Contains(op.comment, "$Value") && op.valueType == "" { - fmt.Printf("missing %s valueType\n", op.name) - } - if op.comment != "" { - buf.WriteString("// " + op.comment + "\n") - } - if op.valueType != "" { - buf.WriteString("// $Value type: " + op.valueType + "\n") - } - fmt.Fprintf(&buf, "Filter%sOp FilterOp = %d\n", op.name, i) - buf.WriteString("\n") - } - buf.WriteString(")\n") - - buf.WriteString("var filterOpNames = map[FilterOp]string{\n") - for _, op := range ops { - fmt.Fprintf(&buf, "Filter%sOp: `%s`,\n", op.name, op.name) - } - buf.WriteString("}\n") - - buf.WriteString("var filterOpFlags = map[FilterOp]uint64{\n") - for _, op := range ops { - if op.flags == 0 { - continue - } - parts := make([]string, 0, 1) - if op.flags&flagIsBinaryExpr != 0 { - parts = append(parts, "flagIsBinaryExpr") - } - if op.flags&flagIsBasicLit != 0 { - parts = append(parts, "flagIsBasicLit") - } - if op.flags&flagHasVar != 0 { - parts = append(parts, "flagHasVar") - } - fmt.Fprintf(&buf, "Filter%sOp: %s,\n", op.name, strings.Join(parts, " | ")) - } - buf.WriteString("}\n") - - pretty, err := format.Source(buf.Bytes()) - if err != nil { - panic(err) - } - - if err := os.WriteFile("filter_op.gen.go", pretty, 0644); err != nil { - panic(err) - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go deleted file mode 100644 index b89481168..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go +++ /dev/null @@ -1,113 +0,0 @@ -package ir - -import ( - "fmt" - "strings" -) - -type File struct { - PkgPath string - - RuleGroups []RuleGroup - - CustomDecls []string - - BundleImports []BundleImport -} - -type BundleImport struct { - Line int - - PkgPath string - Prefix string -} - -type RuleGroup struct { - Line int - Name string - MatcherName string - - DocTags []string - DocSummary string - DocBefore string - DocAfter string - DocNote string - - Imports []PackageImport - - Rules []Rule -} - -type PackageImport struct { - Path string - Name string -} - -type Rule struct { - Line int - - SyntaxPatterns []PatternString - CommentPatterns []PatternString - - ReportTemplate string - SuggestTemplate string - DoFuncName string - - WhereExpr FilterExpr - - LocationVar string -} - -type PatternString struct { - Line int - Value string -} - -// stringer -type=FilterOp -trimprefix=Filter - -//go:generate go run ./gen_filter_op.go -type FilterOp int - -func (op FilterOp) String() string { return filterOpNames[op] } - -type FilterExpr struct { - Line int - - Op FilterOp - Src string - Value interface{} - Args []FilterExpr -} - -func (e FilterExpr) IsValid() bool { return e.Op != FilterInvalidOp } - -func (e FilterExpr) IsBinaryExpr() bool { return filterOpFlags[e.Op]&flagIsBinaryExpr != 0 } -func (e FilterExpr) IsBasicLit() bool { return filterOpFlags[e.Op]&flagIsBasicLit != 0 } -func (e FilterExpr) HasVar() bool { return filterOpFlags[e.Op]&flagHasVar != 0 } - -func (e FilterExpr) String() string { - switch e.Op { - case FilterStringOp: - return `"` + e.Value.(string) + `"` - case FilterIntOp: - return fmt.Sprint(e.Value.(int64)) - } - parts := make([]string, 0, len(e.Args)+2) - parts = append(parts, e.Op.String()) - if e.Value != nil { - parts = append(parts, fmt.Sprintf("[%#v]", e.Value)) - } - for _, arg := range e.Args { - parts = append(parts, arg.String()) - } - if len(parts) == 1 { - return parts[0] - } - return "(" + strings.Join(parts, " ") + ")" -} - -const ( - flagIsBinaryExpr uint64 = 1 << iota - flagIsBasicLit - flagHasVar -) diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go deleted file mode 100644 index 90dea56ac..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go +++ /dev/null @@ -1,890 +0,0 @@ -package ruleguard - -import ( - "bytes" - "fmt" - "go/ast" - "go/constant" - "go/parser" - "go/token" - "go/types" - "os" - "regexp" - - "github.com/quasilyte/gogrep" - "github.com/quasilyte/gogrep/nodetag" - - "github.com/quasilyte/go-ruleguard/ruleguard/goutil" - "github.com/quasilyte/go-ruleguard/ruleguard/ir" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/textmatch" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" -) - -type irLoaderConfig struct { - ctx *LoadContext - - state *engineState - - importer *goImporter - - itab *typematch.ImportsTab - - pkg *types.Package - - gogrepFset *token.FileSet - - prefix string - importedPkg string -} - -type irLoader struct { - state *engineState - ctx *LoadContext - itab *typematch.ImportsTab - - pkg *types.Package - - file *ir.File - gogrepFset *token.FileSet - - filename string - res *goRuleSet - - importer *goImporter - - group *GoRuleGroup - - prefix string // For imported packages, a prefix that is added to a rule group name - importedPkg string // Package path; only for imported packages - - imported []*goRuleSet -} - -func newIRLoader(config irLoaderConfig) *irLoader { - return &irLoader{ - state: config.state, - ctx: config.ctx, - importer: config.importer, - itab: config.itab, - pkg: config.pkg, - prefix: config.prefix, - gogrepFset: config.gogrepFset, - } -} - -func (l *irLoader) LoadFile(filename string, f *ir.File) (*goRuleSet, error) { - l.filename = filename - l.file = f - l.res = &goRuleSet{ - universal: &scopedGoRuleSet{}, - groups: make(map[string]*GoRuleGroup), - } - - for _, imp := range f.BundleImports { - if l.importedPkg != "" { - return nil, l.errorf(imp.Line, nil, "imports from imported packages are not supported yet") - } - if err := l.loadBundle(imp); err != nil { - return nil, err - } - } - - if err := l.compileFilterFuncs(filename, f); err != nil { - return nil, err - } - - for i := range f.RuleGroups { - if err := l.loadRuleGroup(&f.RuleGroups[i]); err != nil { - return nil, err - } - } - - if len(l.imported) != 0 { - toMerge := []*goRuleSet{l.res} - toMerge = append(toMerge, l.imported...) - merged, err := mergeRuleSets(toMerge) - if err != nil { - return nil, err - } - l.res = merged - } - - return l.res, nil -} - -func (l *irLoader) importErrorf(line int, wrapped error, format string, args ...interface{}) error { - return &ImportError{ - msg: fmt.Sprintf("%s:%d: %s", l.filename, line, fmt.Sprintf(format, args...)), - err: wrapped, - } -} - -func (l *irLoader) errorf(line int, wrapped error, format string, args ...interface{}) error { - if wrapped == nil { - return fmt.Errorf("%s:%d: %s", l.filename, line, fmt.Sprintf(format, args...)) - } - return fmt.Errorf("%s:%d: %s: %w", l.filename, line, fmt.Sprintf(format, args...), wrapped) -} - -func (l *irLoader) loadBundle(bundle ir.BundleImport) error { - files, err := findBundleFiles(bundle.PkgPath) - if err != nil { - return l.errorf(bundle.Line, err, "can't find imported bundle files") - } - for _, filename := range files { - rset, err := l.loadExternFile(bundle.Prefix, bundle.PkgPath, filename) - if err != nil { - return l.errorf(bundle.Line, err, "error during bundle file loading") - } - l.imported = append(l.imported, rset) - } - - return nil -} - -func (l *irLoader) loadExternFile(prefix, pkgPath, filename string) (*goRuleSet, error) { - src, err := os.ReadFile(filename) - if err != nil { - return nil, err - } - irfile, pkg, err := convertAST(l.ctx, l.importer, filename, src) - if err != nil { - return nil, err - } - config := irLoaderConfig{ - state: l.state, - ctx: l.ctx, - importer: l.importer, - prefix: prefix, - pkg: pkg, - importedPkg: pkgPath, - itab: l.itab, - gogrepFset: l.gogrepFset, - } - rset, err := newIRLoader(config).LoadFile(filename, irfile) - if err != nil { - return nil, fmt.Errorf("%s: %w", l.importedPkg, err) - } - return rset, nil -} - -func (l *irLoader) compileFilterFuncs(filename string, irfile *ir.File) error { - if len(irfile.CustomDecls) == 0 { - return nil - } - - var buf bytes.Buffer - buf.WriteString("package gorules\n") - buf.WriteString("import \"github.com/quasilyte/go-ruleguard/dsl\"\n") - buf.WriteString("import \"github.com/quasilyte/go-ruleguard/dsl/types\"\n") - for _, src := range irfile.CustomDecls { - buf.WriteString(src) - buf.WriteString("\n") - } - buf.WriteString("type _ = dsl.Matcher\n") - buf.WriteString("type _ = types.Type\n") - - fset := token.NewFileSet() - f, err := goutil.LoadGoFile(goutil.LoadConfig{ - Fset: fset, - Filename: filename, - Data: &buf, - Importer: l.importer, - }) - if err != nil { - // If this ever happens, user will get unexpected error - // lines for it; but we should trust that 99.9% errors - // should be caught at irconv phase so we get a valid Go - // source here as well? - return fmt.Errorf("parse custom decls: %w", err) - } - - for _, decl := range f.Syntax.Decls { - decl, ok := decl.(*ast.FuncDecl) - if !ok { - continue - } - ctx := &quasigo.CompileContext{ - Env: l.state.env, - Package: f.Pkg, - Types: f.Types, - Fset: fset, - } - compiled, err := quasigo.Compile(ctx, decl) - if err != nil { - return err - } - if l.ctx.DebugFunc == decl.Name.String() { - l.ctx.DebugPrint(quasigo.Disasm(l.state.env, compiled)) - } - ctx.Env.AddFunc(f.Pkg.Path(), decl.Name.String(), compiled) - } - - return nil -} - -func (l *irLoader) loadRuleGroup(group *ir.RuleGroup) error { - l.group = &GoRuleGroup{ - Line: group.Line, - Filename: l.filename, - Name: group.Name, - DocSummary: group.DocSummary, - DocBefore: group.DocBefore, - DocAfter: group.DocAfter, - DocNote: group.DocNote, - DocTags: group.DocTags, - } - if l.prefix != "" { - l.group.Name = l.prefix + "/" + l.group.Name - } - - if l.ctx.GroupFilter != nil && !l.ctx.GroupFilter(l.group) { - return nil // Skip this group - } - if _, ok := l.res.groups[l.group.Name]; ok { - panic(fmt.Sprintf("duplicated function %s after the typecheck", l.group.Name)) // Should never happen - } - l.res.groups[l.group.Name] = l.group - - l.itab.EnterScope() - defer l.itab.LeaveScope() - - for _, imported := range group.Imports { - l.itab.Load(imported.Name, imported.Path) - } - - for i := range group.Rules { - rule := &group.Rules[i] - if err := l.loadRule(group, rule); err != nil { - return err - } - } - - return nil -} - -func (l *irLoader) loadRule(group *ir.RuleGroup, rule *ir.Rule) error { - proto := goRule{ - line: rule.Line, - group: l.group, - suggestion: rule.SuggestTemplate, - msg: rule.ReportTemplate, - location: rule.LocationVar, - } - - if rule.DoFuncName != "" { - doFn := l.state.env.GetFunc(l.file.PkgPath, rule.DoFuncName) - if doFn == nil { - return l.errorf(rule.Line, nil, "can't find a compiled version of %s", rule.DoFuncName) - } - proto.do = doFn - } - - info := filterInfo{ - Vars: make(map[string]struct{}), - group: group, - } - if rule.WhereExpr.IsValid() { - filter, err := l.newFilter(rule.WhereExpr, &info) - if err != nil { - return err - } - proto.filter = filter - } - - for _, pat := range rule.SyntaxPatterns { - if err := l.loadSyntaxRule(group, proto, info, rule, pat.Value, pat.Line); err != nil { - return err - } - } - for _, pat := range rule.CommentPatterns { - if err := l.loadCommentRule(proto, rule, pat.Value, pat.Line); err != nil { - return err - } - } - return nil -} - -func (l *irLoader) loadCommentRule(resultProto goRule, rule *ir.Rule, src string, line int) error { - dst := l.res.universal - pat, err := regexp.Compile(src) - if err != nil { - return l.errorf(rule.Line, err, "compile regexp") - } - resultBase := resultProto - resultBase.line = line - result := goCommentRule{ - base: resultProto, - pat: pat, - captureGroups: regexpHasCaptureGroups(src), - } - dst.commentRules = append(dst.commentRules, result) - - return nil -} - -func (l *irLoader) gogrepCompile(group *ir.RuleGroup, src string) (*gogrep.Pattern, gogrep.PatternInfo, error) { - var imports map[string]string - if len(group.Imports) != 0 { - imports = make(map[string]string) - for _, imported := range group.Imports { - imports[imported.Name] = imported.Path - } - } - - gogrepConfig := gogrep.CompileConfig{ - Fset: l.gogrepFset, - Src: src, - Strict: false, - WithTypes: true, - Imports: imports, - } - return gogrep.Compile(gogrepConfig) -} - -func (l *irLoader) loadSyntaxRule(group *ir.RuleGroup, resultProto goRule, filterInfo filterInfo, rule *ir.Rule, src string, line int) error { - result := resultProto - result.line = line - - pat, info, err := l.gogrepCompile(group, src) - if err != nil { - return l.errorf(rule.Line, err, "parse match pattern") - } - result.pat = pat - - for filterVar := range filterInfo.Vars { - if filterVar == "$$" { - continue // OK: a predefined var for the "entire match" - } - _, ok := info.Vars[filterVar] - if !ok { - return l.errorf(rule.Line, nil, "filter refers to a non-existing var %s", filterVar) - } - } - - dst := l.res.universal - var dstTags []nodetag.Value - switch tag := pat.NodeTag(); tag { - case nodetag.Unknown: - return l.errorf(rule.Line, nil, "can't infer a tag of %s", src) - case nodetag.Node: - return l.errorf(rule.Line, nil, "%s pattern is too general", src) - case nodetag.StmtList: - dstTags = []nodetag.Value{ - nodetag.BlockStmt, - nodetag.CaseClause, - nodetag.CommClause, - } - case nodetag.ExprList: - dstTags = []nodetag.Value{ - nodetag.CallExpr, - nodetag.CompositeLit, - nodetag.ReturnStmt, - } - default: - dstTags = []nodetag.Value{tag} - } - for _, tag := range dstTags { - dst.rulesByTag[tag] = append(dst.rulesByTag[tag], result) - } - dst.categorizedNum++ - - return nil -} - -func (l *irLoader) unwrapTypeExpr(filter ir.FilterExpr) (types.Type, error) { - typeString := l.unwrapStringExpr(filter) - if typeString == "" { - return nil, l.errorf(filter.Line, nil, "expected a non-empty type string") - } - typ, err := typeFromString(typeString) - if err != nil { - return nil, l.errorf(filter.Line, err, "parse type expr") - } - if typ == nil { - return nil, l.errorf(filter.Line, nil, "can't convert %s into a type constraint yet", typeString) - } - return typ, nil -} - -func (l *irLoader) unwrapFuncRefExpr(filter ir.FilterExpr) (*types.Func, error) { - s := l.unwrapStringExpr(filter) - if s == "" { - return nil, l.errorf(filter.Line, nil, "expected a non-empty func ref string") - } - - n, err := parser.ParseExpr(s) - if err != nil { - return nil, err - } - - switch n := n.(type) { - case *ast.CallExpr: - // TODO: implement this. - return nil, l.errorf(filter.Line, nil, "inline func signatures are not supported yet") - case *ast.SelectorExpr: - funcName := n.Sel.Name - pkgAndType, ok := n.X.(*ast.SelectorExpr) - if !ok { - return nil, l.errorf(filter.Line, nil, "invalid selector expression") - } - pkgID, ok := pkgAndType.X.(*ast.Ident) - if !ok { - return nil, l.errorf(filter.Line, nil, "invalid package name selector part") - } - pkgName := pkgID.Name - typeName := pkgAndType.Sel.Name - fqn := pkgName + "." + typeName - typ, err := l.state.FindType(l.importer, l.pkg, fqn) - if err != nil { - return nil, l.errorf(filter.Line, nil, "can't find %s type", fqn) - } - switch typ := typ.Underlying().(type) { - case *types.Interface: - for i := 0; i < typ.NumMethods(); i++ { - fn := typ.Method(i) - if fn.Name() == funcName { - return fn, nil - } - } - default: - return nil, l.errorf(filter.Line, nil, "only interfaces are supported, but %s is %T", fqn, typ) - } - - default: - return nil, l.errorf(filter.Line, nil, "unexpected %T node", n) - } - - return nil, nil -} - -func (l *irLoader) unwrapInterfaceExpr(filter ir.FilterExpr) (*types.Interface, error) { - typeString := l.unwrapStringExpr(filter) - if typeString == "" { - return nil, l.errorf(filter.Line, nil, "expected a non-empty type name string") - } - - typ, err := l.state.FindType(l.importer, l.pkg, typeString) - if err == nil { - iface, ok := typ.Underlying().(*types.Interface) - if !ok { - return nil, l.errorf(filter.Line, nil, "%s is not an interface type", typeString) - } - return iface, nil - } - - n, err := parser.ParseExpr(typeString) - if err != nil { - return nil, l.errorf(filter.Line, err, "parse %s type expr", typeString) - } - qn, ok := n.(*ast.SelectorExpr) - if !ok { - return nil, l.errorf(filter.Line, nil, "can't resolve %s type; try a fully-qualified name", typeString) - } - pkgName, ok := qn.X.(*ast.Ident) - if !ok { - return nil, l.errorf(filter.Line, nil, "invalid package name") - } - pkgPath, ok := l.itab.Lookup(pkgName.Name) - if !ok { - return nil, l.errorf(filter.Line, nil, "package %s is not imported", pkgName.Name) - } - pkg, err := l.importer.Import(pkgPath) - if err != nil { - return nil, l.importErrorf(filter.Line, err, "can't load %s", pkgPath) - } - obj := pkg.Scope().Lookup(qn.Sel.Name) - if obj == nil { - return nil, l.errorf(filter.Line, nil, "%s is not found in %s", qn.Sel.Name, pkgPath) - } - iface, ok := obj.Type().Underlying().(*types.Interface) - if !ok { - return nil, l.errorf(filter.Line, nil, "%s is not an interface type", qn.Sel.Name) - } - return iface, nil -} - -func (l *irLoader) unwrapRegexpExpr(filter ir.FilterExpr) (textmatch.Pattern, error) { - patternString := l.unwrapStringExpr(filter) - if patternString == "" { - return nil, l.errorf(filter.Line, nil, "expected a non-empty regexp pattern argument") - } - re, err := textmatch.Compile(patternString) - if err != nil { - return nil, l.errorf(filter.Line, err, "compile regexp") - } - return re, nil -} - -func (l *irLoader) unwrapNodeTagExpr(filter ir.FilterExpr) (nodetag.Value, error) { - typeString := l.unwrapStringExpr(filter) - if typeString == "" { - return nodetag.Unknown, l.errorf(filter.Line, nil, "expected a non-empty string argument") - } - tag := nodetag.FromString(typeString) - if tag == nodetag.Unknown { - return tag, l.errorf(filter.Line, nil, "%s is not a valid go/ast type name", typeString) - } - return tag, nil -} - -func (l *irLoader) unwrapStringExpr(filter ir.FilterExpr) string { - if filter.Op == ir.FilterStringOp { - return filter.Value.(string) - } - return "" -} - -func (l *irLoader) stringToBasicKind(s string) types.BasicInfo { - switch s { - case "integer": - return types.IsInteger - case "unsigned": - return types.IsUnsigned - case "float": - return types.IsFloat - case "complex": - return types.IsComplex - case "untyped": - return types.IsUnsigned - case "numeric": - return types.IsNumeric - default: - return 0 - } -} - -func (l *irLoader) newFilter(filter ir.FilterExpr, info *filterInfo) (matchFilter, error) { - if filter.HasVar() { - info.Vars[filter.Value.(string)] = struct{}{} - } - - if filter.IsBinaryExpr() { - return l.newBinaryExprFilter(filter, info) - } - - result := matchFilter{src: filter.Src} - - switch filter.Op { - case ir.FilterNotOp: - x, err := l.newFilter(filter.Args[0], info) - if err != nil { - return result, err - } - result.fn = makeNotFilter(result.src, x) - - case ir.FilterVarTextMatchesOp: - re, err := l.unwrapRegexpExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeTextMatchesFilter(result.src, filter.Value.(string), re) - - case ir.FilterVarObjectIsOp: - typeString := l.unwrapStringExpr(filter.Args[0]) - if typeString == "" { - return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") - } - switch typeString { - case "Func", "Var", "Const", "TypeName", "Label", "PkgName", "Builtin", "Nil": - // OK. - default: - return result, l.errorf(filter.Line, nil, "%s is not a valid go/types object name", typeString) - } - result.fn = makeObjectIsFilter(result.src, filter.Value.(string), typeString) - - case ir.FilterRootNodeParentIsOp: - tag, err := l.unwrapNodeTagExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeRootParentNodeIsFilter(result.src, tag) - - case ir.FilterVarNodeIsOp: - tag, err := l.unwrapNodeTagExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeNodeIsFilter(result.src, filter.Value.(string), tag) - - case ir.FilterRootSinkTypeIsOp: - typeString := l.unwrapStringExpr(filter.Args[0]) - if typeString == "" { - return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") - } - ctx := typematch.Context{Itab: l.itab} - pat, err := typematch.Parse(&ctx, typeString) - if err != nil { - return result, l.errorf(filter.Line, err, "parse type expr") - } - result.fn = makeRootSinkTypeIsFilter(result.src, pat) - - case ir.FilterVarTypeHasPointersOp: - result.fn = makeTypeHasPointersFilter(result.src, filter.Value.(string)) - - case ir.FilterVarTypeOfKindOp, ir.FilterVarTypeUnderlyingOfKindOp: - kindString := l.unwrapStringExpr(filter.Args[0]) - if kindString == "" { - return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") - } - underlying := filter.Op == ir.FilterVarTypeUnderlyingOfKindOp - switch kindString { - case "signed": - result.fn = makeTypeIsSignedFilter(result.src, filter.Value.(string), underlying) - case "int": - result.fn = makeTypeIsIntUintFilter(result.src, filter.Value.(string), underlying, types.Int) - case "uint": - result.fn = makeTypeIsIntUintFilter(result.src, filter.Value.(string), underlying, types.Uint) - default: - kind := l.stringToBasicKind(kindString) - if kind == 0 { - return result, l.errorf(filter.Line, nil, "unknown kind %s", kindString) - } - result.fn = makeTypeOfKindFilter(result.src, filter.Value.(string), underlying, kind) - } - - case ir.FilterVarTypeIdenticalToOp: - lhsVarname := filter.Value.(string) - rhsVarname := filter.Args[0].Value.(string) - result.fn = makeTypesIdenticalFilter(result.src, lhsVarname, rhsVarname) - - case ir.FilterVarTypeIsOp, ir.FilterVarTypeUnderlyingIsOp: - typeString := l.unwrapStringExpr(filter.Args[0]) - if typeString == "" { - return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") - } - ctx := typematch.Context{Itab: l.itab} - pat, err := typematch.Parse(&ctx, typeString) - if err != nil { - return result, l.errorf(filter.Line, err, "parse type expr") - } - underlying := filter.Op == ir.FilterVarTypeUnderlyingIsOp - result.fn = makeTypeIsFilter(result.src, filter.Value.(string), underlying, pat) - - case ir.FilterVarTypeConvertibleToOp: - dstType, err := l.unwrapTypeExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeTypeConvertibleToFilter(result.src, filter.Value.(string), dstType) - - case ir.FilterVarTypeAssignableToOp: - dstType, err := l.unwrapTypeExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeTypeAssignableToFilter(result.src, filter.Value.(string), dstType) - - case ir.FilterVarTypeImplementsOp: - iface, err := l.unwrapInterfaceExpr(filter.Args[0]) - if err != nil { - return result, err - } - result.fn = makeTypeImplementsFilter(result.src, filter.Value.(string), iface) - - case ir.FilterVarTypeHasMethodOp: - fn, err := l.unwrapFuncRefExpr(filter.Args[0]) - if err != nil { - return result, err - } - if fn == nil { - return result, l.errorf(filter.Line, nil, "can't resolve HasMethod() argument") - } - result.fn = makeTypeHasMethodFilter(result.src, filter.Value.(string), fn) - - case ir.FilterVarPureOp: - result.fn = makePureFilter(result.src, filter.Value.(string)) - case ir.FilterVarConstOp: - result.fn = makeConstFilter(result.src, filter.Value.(string)) - case ir.FilterVarObjectIsGlobalOp: - result.fn = makeObjectIsGlobalFilter(result.src, filter.Value.(string)) - case ir.FilterVarObjectIsVariadicParamOp: - result.fn = makeObjectIsVariadicParamFilter(result.src, filter.Value.(string)) - case ir.FilterVarConstSliceOp: - result.fn = makeConstSliceFilter(result.src, filter.Value.(string)) - case ir.FilterVarAddressableOp: - result.fn = makeAddressableFilter(result.src, filter.Value.(string)) - case ir.FilterVarComparableOp: - result.fn = makeComparableFilter(result.src, filter.Value.(string)) - - case ir.FilterFileImportsOp: - result.fn = makeFileImportsFilter(result.src, filter.Value.(string)) - - case ir.FilterDeadcodeOp: - result.fn = makeDeadcodeFilter(result.src) - - case ir.FilterGoVersionEqOp: - version, err := ParseGoVersion(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "parse Go version") - } - result.fn = makeGoVersionFilter(result.src, token.EQL, version) - case ir.FilterGoVersionLessThanOp: - version, err := ParseGoVersion(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "parse Go version") - } - result.fn = makeGoVersionFilter(result.src, token.LSS, version) - case ir.FilterGoVersionGreaterThanOp: - version, err := ParseGoVersion(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "parse Go version") - } - result.fn = makeGoVersionFilter(result.src, token.GTR, version) - case ir.FilterGoVersionLessEqThanOp: - version, err := ParseGoVersion(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "parse Go version") - } - result.fn = makeGoVersionFilter(result.src, token.LEQ, version) - case ir.FilterGoVersionGreaterEqThanOp: - version, err := ParseGoVersion(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "parse Go version") - } - result.fn = makeGoVersionFilter(result.src, token.GEQ, version) - - case ir.FilterFilePkgPathMatchesOp: - re, err := regexp.Compile(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "compile regexp") - } - result.fn = makeFilePkgPathMatchesFilter(result.src, re) - - case ir.FilterFileNameMatchesOp: - re, err := regexp.Compile(filter.Value.(string)) - if err != nil { - return result, l.errorf(filter.Line, err, "compile regexp") - } - result.fn = makeFileNameMatchesFilter(result.src, re) - - case ir.FilterVarContainsOp: - src := filter.Args[0].Value.(string) - pat, _, err := l.gogrepCompile(info.group, src) - if err != nil { - return result, l.errorf(filter.Line, err, "parse contains pattern") - } - result.fn = makeVarContainsFilter(result.src, filter.Value.(string), pat) - - case ir.FilterVarFilterOp: - funcName := filter.Args[0].Value.(string) - userFn := l.state.env.GetFunc(l.file.PkgPath, funcName) - if userFn == nil { - return result, l.errorf(filter.Line, nil, "can't find a compiled version of %s", funcName) - } - result.fn = makeCustomVarFilter(result.src, filter.Value.(string), userFn) - } - - if result.fn == nil { - return result, l.errorf(filter.Line, nil, "unsupported expr: %s (%s)", result.src, filter.Op) - } - - return result, nil -} - -func (l *irLoader) newBinaryExprFilter(filter ir.FilterExpr, info *filterInfo) (matchFilter, error) { - if filter.Op == ir.FilterAndOp || filter.Op == ir.FilterOrOp { - result := matchFilter{src: filter.Src} - lhs, err := l.newFilter(filter.Args[0], info) - if err != nil { - return result, err - } - rhs, err := l.newFilter(filter.Args[1], info) - if err != nil { - return result, err - } - if filter.Op == ir.FilterAndOp { - result.fn = makeAndFilter(lhs, rhs) - } else { - result.fn = makeOrFilter(lhs, rhs) - } - return result, nil - } - - // If constexpr is on the LHS, move it to the right, so the code below - // can imply constants being on the RHS all the time. - if filter.Args[0].IsBasicLit() && !filter.Args[1].IsBasicLit() { - // Just a precaution: if we ever have a float values here, - // we may not want to rearrange anything. - switch filter.Args[0].Value.(type) { - case string, int64: - switch filter.Op { - case ir.FilterEqOp, ir.FilterNeqOp: - // Simple commutative ops. Just swap the args. - newFilter := filter - newFilter.Args = []ir.FilterExpr{filter.Args[1], filter.Args[0]} - return l.newBinaryExprFilter(newFilter, info) - } - } - } - - result := matchFilter{src: filter.Src} - - var tok token.Token - switch filter.Op { - case ir.FilterEqOp: - tok = token.EQL - case ir.FilterNeqOp: - tok = token.NEQ - case ir.FilterGtOp: - tok = token.GTR - case ir.FilterGtEqOp: - tok = token.GEQ - case ir.FilterLtOp: - tok = token.LSS - case ir.FilterLtEqOp: - tok = token.LEQ - default: - return result, l.errorf(filter.Line, nil, "unsupported operator in binary expr: %s", result.src) - } - - lhs := filter.Args[0] - rhs := filter.Args[1] - var rhsValue constant.Value - switch rhs.Op { - case ir.FilterStringOp: - rhsValue = constant.MakeString(rhs.Value.(string)) - case ir.FilterIntOp: - rhsValue = constant.MakeInt64(rhs.Value.(int64)) - } - - switch lhs.Op { - case ir.FilterVarLineOp: - if rhsValue != nil { - result.fn = makeLineConstFilter(result.src, lhs.Value.(string), tok, rhsValue) - } else if rhs.Op == lhs.Op { - result.fn = makeLineFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) - } - case ir.FilterVarTypeSizeOp: - if rhsValue != nil { - result.fn = makeTypeSizeConstFilter(result.src, lhs.Value.(string), tok, rhsValue) - } else { - result.fn = makeTypeSizeFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) - } - case ir.FilterVarValueIntOp: - if rhsValue != nil { - result.fn = makeValueIntConstFilter(result.src, lhs.Value.(string), tok, rhsValue) - } else if rhs.Op == lhs.Op { - result.fn = makeValueIntFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) - } - case ir.FilterVarTextOp: - if rhsValue != nil { - result.fn = makeTextConstFilter(result.src, lhs.Value.(string), tok, rhsValue) - } else if rhs.Op == lhs.Op { - result.fn = makeTextFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) - } - } - - if result.fn == nil { - return result, l.errorf(filter.Line, nil, "unsupported binary expr: %s", result.src) - } - - return result, nil -} - -type filterInfo struct { - Vars map[string]struct{} - - group *ir.RuleGroup -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go deleted file mode 100644 index 62c24bf15..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go +++ /dev/null @@ -1,41 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/ast" - "go/parser" - "go/types" - - "github.com/quasilyte/go-ruleguard/ruleguard/ir" - "github.com/quasilyte/go-ruleguard/ruleguard/irconv" -) - -func convertAST(ctx *LoadContext, imp *goImporter, filename string, src []byte) (*ir.File, *types.Package, error) { - parserFlags := parser.ParseComments - f, err := parser.ParseFile(ctx.Fset, filename, src, parserFlags) - if err != nil { - return nil, nil, fmt.Errorf("parse file error: %w", err) - } - - typechecker := types.Config{Importer: imp} - typesInfo := &types.Info{ - Types: map[ast.Expr]types.TypeAndValue{}, - Uses: map[*ast.Ident]types.Object{}, - Defs: map[*ast.Ident]types.Object{}, - } - pkg, err := typechecker.Check("gorules", ctx.Fset, []*ast.File{f}, typesInfo) - if err != nil { - return nil, nil, fmt.Errorf("typechecker error: %w", err) - } - irconvCtx := &irconv.Context{ - Pkg: pkg, - Types: typesInfo, - Fset: ctx.Fset, - Src: src, - } - irfile, err := irconv.ConvertFile(irconvCtx, f) - if err != nil { - return nil, nil, fmt.Errorf("irconv error: %w", err) - } - return irfile, pkg, nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go deleted file mode 100644 index cc40506af..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go +++ /dev/null @@ -1,857 +0,0 @@ -package irconv - -import ( - "fmt" - "go/ast" - "go/constant" - "go/token" - "go/types" - "path" - "strconv" - "strings" - - "github.com/go-toolsmith/astcopy" - "golang.org/x/tools/go/ast/astutil" - - "github.com/quasilyte/go-ruleguard/ruleguard/goutil" - "github.com/quasilyte/go-ruleguard/ruleguard/ir" -) - -type Context struct { - Pkg *types.Package - Types *types.Info - Fset *token.FileSet - Src []byte -} - -func ConvertFile(ctx *Context, f *ast.File) (result *ir.File, err error) { - defer func() { - if err != nil { - return - } - rv := recover() - if rv == nil { - return - } - if convErr, ok := rv.(convError); ok { - err = convErr.err - return - } - panic(rv) // not our panic - }() - - conv := &converter{ - types: ctx.Types, - pkg: ctx.Pkg, - fset: ctx.Fset, - src: ctx.Src, - } - result = conv.ConvertFile(f) - return result, nil -} - -type convError struct { - err error -} - -type localMacroFunc struct { - name string - params []string - template ast.Expr -} - -type converter struct { - types *types.Info - pkg *types.Package - fset *token.FileSet - src []byte - - group *ir.RuleGroup - groupFuncs []localMacroFunc - - dslPkgname string // The local name of the "ruleguard/dsl" package (usually its just "dsl") -} - -func (conv *converter) errorf(n ast.Node, format string, args ...interface{}) convError { - loc := conv.fset.Position(n.Pos()) - msg := fmt.Sprintf(format, args...) - return convError{err: fmt.Errorf("%s:%d: %s", loc.Filename, loc.Line, msg)} -} - -func (conv *converter) ConvertFile(f *ast.File) *ir.File { - result := &ir.File{ - PkgPath: conv.pkg.Path(), - } - - conv.dslPkgname = "dsl" - - for _, imp := range f.Imports { - importPath, err := strconv.Unquote(imp.Path.Value) - if err != nil { - panic(conv.errorf(imp, "unquote %s import path: %s", imp.Path.Value, err)) - } - if importPath == "github.com/quasilyte/go-ruleguard/dsl" { - if imp.Name != nil { - conv.dslPkgname = imp.Name.Name - } - } - // Right now this list is hardcoded from the knowledge of which - // stdlib packages are supported inside the bytecode. - switch importPath { - case "fmt", "strings", "strconv": - conv.addCustomImport(result, importPath) - } - } - - for _, decl := range f.Decls { - funcDecl, ok := decl.(*ast.FuncDecl) - if !ok { - genDecl := decl.(*ast.GenDecl) - if genDecl.Tok != token.IMPORT { - conv.addCustomDecl(result, decl) - } - continue - } - - if funcDecl.Name.String() == "init" { - conv.convertInitFunc(result, funcDecl) - continue - } - - if conv.isMatcherFunc(funcDecl) { - result.RuleGroups = append(result.RuleGroups, *conv.convertRuleGroup(funcDecl)) - } else { - conv.addCustomDecl(result, funcDecl) - } - } - - return result -} - -func (conv *converter) convertInitFunc(dst *ir.File, decl *ast.FuncDecl) { - for _, stmt := range decl.Body.List { - exprStmt, ok := stmt.(*ast.ExprStmt) - if !ok { - panic(conv.errorf(stmt, "unsupported statement")) - } - call, ok := exprStmt.X.(*ast.CallExpr) - if !ok { - panic(conv.errorf(stmt, "unsupported expr")) - } - fn, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - panic(conv.errorf(stmt, "unsupported call")) - } - pkg, ok := fn.X.(*ast.Ident) - if !ok || pkg.Name != conv.dslPkgname { - panic(conv.errorf(stmt, "unsupported call")) - } - - switch fn.Sel.Name { - case "ImportRules": - prefix := conv.parseStringArg(call.Args[0]) - bundleSelector, ok := call.Args[1].(*ast.SelectorExpr) - if !ok { - panic(conv.errorf(call.Args[1], "expected a `pkgname.Bundle` argument")) - } - bundleObj := conv.types.ObjectOf(bundleSelector.Sel) - dst.BundleImports = append(dst.BundleImports, ir.BundleImport{ - Prefix: prefix, - PkgPath: bundleObj.Pkg().Path(), - Line: conv.fset.Position(exprStmt.Pos()).Line, - }) - - default: - panic(conv.errorf(stmt, "unsupported %s call", fn.Sel.Name)) - } - } -} - -func (conv *converter) addCustomImport(dst *ir.File, pkgPath string) { - dst.CustomDecls = append(dst.CustomDecls, `import "`+pkgPath+`"`) -} - -func (conv *converter) addCustomDecl(dst *ir.File, decl ast.Decl) { - begin := conv.fset.Position(decl.Pos()) - end := conv.fset.Position(decl.End()) - src := conv.src[begin.Offset:end.Offset] - dst.CustomDecls = append(dst.CustomDecls, string(src)) -} - -func (conv *converter) isMatcherFunc(f *ast.FuncDecl) bool { - typ := conv.types.ObjectOf(f.Name).Type().(*types.Signature) - return typ.Results().Len() == 0 && - typ.Params().Len() == 1 && - typ.Params().At(0).Type().String() == "github.com/quasilyte/go-ruleguard/dsl.Matcher" -} - -func (conv *converter) convertRuleGroup(decl *ast.FuncDecl) *ir.RuleGroup { - result := &ir.RuleGroup{ - Line: conv.fset.Position(decl.Name.Pos()).Line, - } - conv.group = result - conv.groupFuncs = conv.groupFuncs[:0] - - result.Name = decl.Name.String() - result.MatcherName = decl.Type.Params.List[0].Names[0].String() - - if decl.Doc != nil { - conv.convertDocComments(decl.Doc) - } - - seenRules := false - for _, stmt := range decl.Body.List { - if assign, ok := stmt.(*ast.AssignStmt); ok && assign.Tok == token.DEFINE { - conv.localDefine(assign) - continue - } - - if _, ok := stmt.(*ast.DeclStmt); ok { - continue - } - stmtExpr, ok := stmt.(*ast.ExprStmt) - if !ok { - panic(conv.errorf(stmt, "expected a %s method call, found %s", result.MatcherName, goutil.SprintNode(conv.fset, stmt))) - } - call, ok := stmtExpr.X.(*ast.CallExpr) - if !ok { - panic(conv.errorf(stmt, "expected a %s method call, found %s", result.MatcherName, goutil.SprintNode(conv.fset, stmt))) - } - - switch conv.matcherMethodName(call) { - case "Import": - if seenRules { - panic(conv.errorf(call, "Import() should be used before any rules definitions")) - } - conv.doMatcherImport(call) - default: - seenRules = true - conv.convertRuleExpr(call) - } - } - - return result -} - -func (conv *converter) findLocalMacro(call *ast.CallExpr) *localMacroFunc { - fn, ok := call.Fun.(*ast.Ident) - if !ok { - return nil - } - for i := range conv.groupFuncs { - if conv.groupFuncs[i].name == fn.Name { - return &conv.groupFuncs[i] - } - } - return nil -} - -func (conv *converter) expandMacro(macro *localMacroFunc, call *ast.CallExpr) ir.FilterExpr { - // Check that call args are OK. - // Since "function calls" are implemented as a macro expansion here, - // we don't allow arguments that have a non-trivial evaluation. - isSafe := func(arg ast.Expr) bool { - switch arg := astutil.Unparen(arg).(type) { - case *ast.BasicLit, *ast.Ident: - return true - - case *ast.IndexExpr: - mapIdent, ok := astutil.Unparen(arg.X).(*ast.Ident) - if !ok { - return false - } - if mapIdent.Name != conv.group.MatcherName { - return false - } - key, ok := astutil.Unparen(arg.Index).(*ast.BasicLit) - if !ok || key.Kind != token.STRING { - return false - } - return true - - default: - return false - } - } - args := map[string]ast.Expr{} - for i, arg := range call.Args { - paramName := macro.params[i] - if !isSafe(arg) { - panic(conv.errorf(arg, "unsupported/too complex %s argument", paramName)) - } - args[paramName] = astutil.Unparen(arg) - } - - body := astcopy.Expr(macro.template) - expanded := astutil.Apply(body, nil, func(cur *astutil.Cursor) bool { - if ident, ok := cur.Node().(*ast.Ident); ok { - arg, ok := args[ident.Name] - if ok { - cur.Replace(arg) - return true - } - } - // astcopy above will copy the AST tree, but it won't update - // the associated types.Info map of const values. - // We'll try to solve that issue at least partially here. - if lit, ok := cur.Node().(*ast.BasicLit); ok { - switch lit.Kind { - case token.STRING: - val, err := strconv.Unquote(lit.Value) - if err == nil { - conv.types.Types[lit] = types.TypeAndValue{ - Type: types.Typ[types.UntypedString], - Value: constant.MakeString(val), - } - } - case token.INT: - val, err := strconv.ParseInt(lit.Value, 0, 64) - if err == nil { - conv.types.Types[lit] = types.TypeAndValue{ - Type: types.Typ[types.UntypedInt], - Value: constant.MakeInt64(val), - } - } - case token.FLOAT: - val, err := strconv.ParseFloat(lit.Value, 64) - if err == nil { - conv.types.Types[lit] = types.TypeAndValue{ - Type: types.Typ[types.UntypedFloat], - Value: constant.MakeFloat64(val), - } - } - } - } - return true - }) - - return conv.convertFilterExpr(expanded.(ast.Expr)) -} - -func (conv *converter) localDefine(assign *ast.AssignStmt) { - if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 { - panic(conv.errorf(assign, "multi-value := is not supported")) - } - lhs, ok := assign.Lhs[0].(*ast.Ident) - if !ok { - panic(conv.errorf(assign.Lhs[0], "only simple ident lhs is supported")) - } - rhs := assign.Rhs[0] - fn, ok := rhs.(*ast.FuncLit) - if !ok { - panic(conv.errorf(rhs, "only func literals are supported on the rhs")) - } - typ := conv.types.TypeOf(fn).(*types.Signature) - isBoolResult := typ.Results() != nil && - typ.Results().Len() == 1 && - typ.Results().At(0).Type() == types.Typ[types.Bool] - if !isBoolResult { - var loc ast.Node = fn.Type - if fn.Type.Results != nil { - loc = fn.Type.Results - } - panic(conv.errorf(loc, "only funcs returning bool are supported")) - } - if len(fn.Body.List) != 1 { - panic(conv.errorf(fn.Body, "only simple 1 return statement funcs are supported")) - } - stmt, ok := fn.Body.List[0].(*ast.ReturnStmt) - if !ok { - panic(conv.errorf(fn.Body.List[0], "expected a return statement, found %T", fn.Body.List[0])) - } - var params []string - for _, field := range fn.Type.Params.List { - for _, id := range field.Names { - params = append(params, id.Name) - } - } - macro := localMacroFunc{ - name: lhs.Name, - params: params, - template: stmt.Results[0], - } - conv.groupFuncs = append(conv.groupFuncs, macro) -} - -func (conv *converter) doMatcherImport(call *ast.CallExpr) { - pkgPath := conv.parseStringArg(call.Args[0]) - pkgName := path.Base(pkgPath) - conv.group.Imports = append(conv.group.Imports, ir.PackageImport{ - Path: pkgPath, - Name: pkgName, - }) -} - -func (conv *converter) matcherMethodName(call *ast.CallExpr) string { - selector, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - return "" - } - id, ok := selector.X.(*ast.Ident) - if !ok || id.Name != conv.group.MatcherName { - return "" - } - return selector.Sel.Name -} - -func (conv *converter) convertDocComments(comment *ast.CommentGroup) { - knownPragmas := []string{ - "tags", - "summary", - "before", - "after", - "note", - } - - for _, c := range comment.List { - if !strings.HasPrefix(c.Text, "//doc:") { - continue - } - s := strings.TrimPrefix(c.Text, "//doc:") - var pragma string - for i := range knownPragmas { - if strings.HasPrefix(s, knownPragmas[i]) { - pragma = knownPragmas[i] - break - } - } - if pragma == "" { - panic(conv.errorf(c, "unrecognized 'doc' pragma in comment")) - } - s = strings.TrimPrefix(s, pragma) - s = strings.TrimSpace(s) - switch pragma { - case "summary": - conv.group.DocSummary = s - case "before": - conv.group.DocBefore = s - case "after": - conv.group.DocAfter = s - case "note": - conv.group.DocNote = s - case "tags": - conv.group.DocTags = strings.Fields(s) - default: - panic("unhandled 'doc' pragma: " + pragma) // Should never happen - } - } -} - -func (conv *converter) convertRuleExpr(call *ast.CallExpr) { - origCall := call - var ( - matchArgs *[]ast.Expr - matchCommentArgs *[]ast.Expr - whereArgs *[]ast.Expr - suggestArgs *[]ast.Expr - reportArgs *[]ast.Expr - atArgs *[]ast.Expr - doArgs *[]ast.Expr - ) - - for { - chain, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - break - } - switch chain.Sel.Name { - case "Match": - if matchArgs != nil { - panic(conv.errorf(chain.Sel, "Match() can't be repeated")) - } - if matchCommentArgs != nil { - panic(conv.errorf(chain.Sel, "Match() and MatchComment() can't be combined")) - } - matchArgs = &call.Args - case "MatchComment": - if matchCommentArgs != nil { - panic(conv.errorf(chain.Sel, "MatchComment() can't be repeated")) - } - if matchArgs != nil { - panic(conv.errorf(chain.Sel, "Match() and MatchComment() can't be combined")) - } - matchCommentArgs = &call.Args - case "Where": - if whereArgs != nil { - panic(conv.errorf(chain.Sel, "Where() can't be repeated")) - } - whereArgs = &call.Args - case "Suggest": - if suggestArgs != nil { - panic(conv.errorf(chain.Sel, "Suggest() can't be repeated")) - } - suggestArgs = &call.Args - case "Report": - if reportArgs != nil { - panic(conv.errorf(chain.Sel, "Report() can't be repeated")) - } - reportArgs = &call.Args - case "Do": - doArgs = &call.Args - case "At": - if atArgs != nil { - panic(conv.errorf(chain.Sel, "At() can't be repeated")) - } - atArgs = &call.Args - default: - panic(conv.errorf(chain.Sel, "unexpected %s method", chain.Sel.Name)) - } - call, ok = chain.X.(*ast.CallExpr) - if !ok { - break - } - } - - // AST patterns for Match() or regexp patterns for MatchComment(). - var alternatives []string - var alternativeLines []int - - if matchArgs == nil && matchCommentArgs == nil { - panic(conv.errorf(origCall, "missing Match() or MatchComment() call")) - } - - if matchArgs != nil { - for _, arg := range *matchArgs { - alternatives = append(alternatives, conv.parseStringArg(arg)) - alternativeLines = append(alternativeLines, conv.fset.Position(arg.Pos()).Line) - } - } else { - for _, arg := range *matchCommentArgs { - alternatives = append(alternatives, conv.parseStringArg(arg)) - alternativeLines = append(alternativeLines, conv.fset.Position(arg.Pos()).Line) - } - } - - rule := ir.Rule{Line: conv.fset.Position(origCall.Pos()).Line} - - if atArgs != nil { - index, ok := (*atArgs)[0].(*ast.IndexExpr) - if !ok { - panic(conv.errorf((*atArgs)[0], "expected %s[`varname`] expression", conv.group.MatcherName)) - } - rule.LocationVar = conv.parseStringArg(index.Index) - } - - if whereArgs != nil { - rule.WhereExpr = conv.convertFilterExpr((*whereArgs)[0]) - } - - if suggestArgs != nil { - rule.SuggestTemplate = conv.parseStringArg((*suggestArgs)[0]) - } - - if suggestArgs == nil && reportArgs == nil && doArgs == nil { - panic(conv.errorf(origCall, "missing Report(), Suggest() or Do() call")) - } - if doArgs != nil { - if suggestArgs != nil || reportArgs != nil { - panic(conv.errorf(origCall, "can't combine Report/Suggest with Do yet")) - } - if matchCommentArgs != nil { - panic(conv.errorf(origCall, "can't use Do() with MatchComment() yet")) - } - funcName, ok := (*doArgs)[0].(*ast.Ident) - if !ok { - panic(conv.errorf((*doArgs)[0], "only named function args are supported")) - } - rule.DoFuncName = funcName.String() - } else { - if reportArgs == nil { - rule.ReportTemplate = "suggestion: " + rule.SuggestTemplate - } else { - rule.ReportTemplate = conv.parseStringArg((*reportArgs)[0]) - } - } - - for i, alt := range alternatives { - pat := ir.PatternString{ - Line: alternativeLines[i], - Value: alt, - } - if matchArgs != nil { - rule.SyntaxPatterns = append(rule.SyntaxPatterns, pat) - } else { - rule.CommentPatterns = append(rule.CommentPatterns, pat) - } - } - conv.group.Rules = append(conv.group.Rules, rule) -} - -func (conv *converter) convertFilterExpr(e ast.Expr) ir.FilterExpr { - result := conv.convertFilterExprImpl(e) - result.Src = goutil.SprintNode(conv.fset, e) - result.Line = conv.fset.Position(e.Pos()).Line - if !result.IsValid() { - panic(conv.errorf(e, "unsupported expr: %s (%T)", result.Src, e)) - } - return result -} - -func (conv *converter) convertFilterExprImpl(e ast.Expr) ir.FilterExpr { - if cv := conv.types.Types[e].Value; cv != nil { - switch cv.Kind() { - case constant.String: - v := constant.StringVal(cv) - return ir.FilterExpr{Op: ir.FilterStringOp, Value: v} - case constant.Int: - v, ok := constant.Int64Val(cv) - if ok { - return ir.FilterExpr{Op: ir.FilterIntOp, Value: v} - } - } - } - convertExprList := func(list []ast.Expr) []ir.FilterExpr { - if len(list) == 0 { - return nil - } - result := make([]ir.FilterExpr, len(list)) - for i, e := range list { - result[i] = conv.convertFilterExpr(e) - } - return result - } - - switch e := e.(type) { - case *ast.ParenExpr: - return conv.convertFilterExpr(e.X) - - case *ast.UnaryExpr: - x := conv.convertFilterExpr(e.X) - args := []ir.FilterExpr{x} - if e.Op == token.NOT { - return ir.FilterExpr{Op: ir.FilterNotOp, Args: args} - } - - case *ast.BinaryExpr: - x := conv.convertFilterExpr(e.X) - y := conv.convertFilterExpr(e.Y) - args := []ir.FilterExpr{x, y} - switch e.Op { - case token.LAND: - return ir.FilterExpr{Op: ir.FilterAndOp, Args: args} - case token.LOR: - return ir.FilterExpr{Op: ir.FilterOrOp, Args: args} - case token.NEQ: - return ir.FilterExpr{Op: ir.FilterNeqOp, Args: args} - case token.EQL: - return ir.FilterExpr{Op: ir.FilterEqOp, Args: args} - case token.GTR: - return ir.FilterExpr{Op: ir.FilterGtOp, Args: args} - case token.LSS: - return ir.FilterExpr{Op: ir.FilterLtOp, Args: args} - case token.GEQ: - return ir.FilterExpr{Op: ir.FilterGtEqOp, Args: args} - case token.LEQ: - return ir.FilterExpr{Op: ir.FilterLtEqOp, Args: args} - default: - panic(conv.errorf(e, "unexpected binary op: %s", e.Op.String())) - } - - case *ast.SelectorExpr: - op := conv.inspectFilterSelector(e) - switch op.path { - case "Text": - return ir.FilterExpr{Op: ir.FilterVarTextOp, Value: op.varName} - case "Line": - return ir.FilterExpr{Op: ir.FilterVarLineOp, Value: op.varName} - case "Pure": - return ir.FilterExpr{Op: ir.FilterVarPureOp, Value: op.varName} - case "Const": - return ir.FilterExpr{Op: ir.FilterVarConstOp, Value: op.varName} - case "ConstSlice": - return ir.FilterExpr{Op: ir.FilterVarConstSliceOp, Value: op.varName} - case "Addressable": - return ir.FilterExpr{Op: ir.FilterVarAddressableOp, Value: op.varName} - case "Comparable": - return ir.FilterExpr{Op: ir.FilterVarComparableOp, Value: op.varName} - case "Type.Size": - return ir.FilterExpr{Op: ir.FilterVarTypeSizeOp, Value: op.varName} - } - - case *ast.CallExpr: - op := conv.inspectFilterSelector(e) - switch op.path { - case "Deadcode": - return ir.FilterExpr{Op: ir.FilterDeadcodeOp} - case "GoVersion.Eq": - return ir.FilterExpr{Op: ir.FilterGoVersionEqOp, Value: conv.parseStringArg(e.Args[0])} - case "GoVersion.LessThan": - return ir.FilterExpr{Op: ir.FilterGoVersionLessThanOp, Value: conv.parseStringArg(e.Args[0])} - case "GoVersion.GreaterThan": - return ir.FilterExpr{Op: ir.FilterGoVersionGreaterThanOp, Value: conv.parseStringArg(e.Args[0])} - case "GoVersion.LessEqThan": - return ir.FilterExpr{Op: ir.FilterGoVersionLessEqThanOp, Value: conv.parseStringArg(e.Args[0])} - case "GoVersion.GreaterEqThan": - return ir.FilterExpr{Op: ir.FilterGoVersionGreaterEqThanOp, Value: conv.parseStringArg(e.Args[0])} - case "File.Imports": - return ir.FilterExpr{Op: ir.FilterFileImportsOp, Value: conv.parseStringArg(e.Args[0])} - case "File.PkgPath.Matches": - return ir.FilterExpr{Op: ir.FilterFilePkgPathMatchesOp, Value: conv.parseStringArg(e.Args[0])} - case "File.Name.Matches": - return ir.FilterExpr{Op: ir.FilterFileNameMatchesOp, Value: conv.parseStringArg(e.Args[0])} - - case "Contains": - pat := conv.parseStringArg(e.Args[0]) - return ir.FilterExpr{ - Op: ir.FilterVarContainsOp, - Value: op.varName, - Args: []ir.FilterExpr{ - {Op: ir.FilterStringOp, Value: pat}, - }, - } - - case "Type.IdenticalTo": - // TODO: reuse the code with parsing At() args? - index, ok := e.Args[0].(*ast.IndexExpr) - if !ok { - panic(conv.errorf(e.Args[0], "expected %s[`varname`] expression", conv.group.MatcherName)) - } - rhsVarname := conv.parseStringArg(index.Index) - args := []ir.FilterExpr{ - {Op: ir.FilterStringOp, Value: rhsVarname}, - } - return ir.FilterExpr{Op: ir.FilterVarTypeIdenticalToOp, Value: op.varName, Args: args} - - case "Filter": - funcName, ok := e.Args[0].(*ast.Ident) - if !ok { - panic(conv.errorf(e.Args[0], "only named function args are supported")) - } - args := []ir.FilterExpr{ - {Op: ir.FilterFilterFuncRefOp, Value: funcName.String()}, - } - return ir.FilterExpr{Op: ir.FilterVarFilterOp, Value: op.varName, Args: args} - } - - if macro := conv.findLocalMacro(e); macro != nil { - return conv.expandMacro(macro, e) - } - - args := convertExprList(e.Args) - switch op.path { - case "Value.Int": - return ir.FilterExpr{Op: ir.FilterVarValueIntOp, Value: op.varName, Args: args} - case "Text.Matches": - return ir.FilterExpr{Op: ir.FilterVarTextMatchesOp, Value: op.varName, Args: args} - case "Node.Is": - return ir.FilterExpr{Op: ir.FilterVarNodeIsOp, Value: op.varName, Args: args} - case "Node.Parent.Is": - if op.varName != "$$" { - // TODO: remove this restriction. - panic(conv.errorf(e.Args[0], "only $$ parent nodes are implemented")) - } - return ir.FilterExpr{Op: ir.FilterRootNodeParentIsOp, Args: args} - case "Object.Is": - return ir.FilterExpr{Op: ir.FilterVarObjectIsOp, Value: op.varName, Args: args} - case "Object.IsGlobal": - return ir.FilterExpr{Op: ir.FilterVarObjectIsGlobalOp, Value: op.varName} - case "Object.IsVariadicParam": - return ir.FilterExpr{Op: ir.FilterVarObjectIsVariadicParamOp, Value: op.varName} - case "SinkType.Is": - if op.varName != "$$" { - // TODO: remove this restriction. - panic(conv.errorf(e.Args[0], "sink type is only implemented for $$ var")) - } - return ir.FilterExpr{Op: ir.FilterRootSinkTypeIsOp, Value: op.varName, Args: args} - case "Type.HasPointers": - return ir.FilterExpr{Op: ir.FilterVarTypeHasPointersOp, Value: op.varName} - case "Type.Is": - return ir.FilterExpr{Op: ir.FilterVarTypeIsOp, Value: op.varName, Args: args} - case "Type.Underlying.Is": - return ir.FilterExpr{Op: ir.FilterVarTypeUnderlyingIsOp, Value: op.varName, Args: args} - case "Type.OfKind": - return ir.FilterExpr{Op: ir.FilterVarTypeOfKindOp, Value: op.varName, Args: args} - case "Type.Underlying.OfKind": - return ir.FilterExpr{Op: ir.FilterVarTypeUnderlyingOfKindOp, Value: op.varName, Args: args} - case "Type.ConvertibleTo": - return ir.FilterExpr{Op: ir.FilterVarTypeConvertibleToOp, Value: op.varName, Args: args} - case "Type.AssignableTo": - return ir.FilterExpr{Op: ir.FilterVarTypeAssignableToOp, Value: op.varName, Args: args} - case "Type.Implements": - return ir.FilterExpr{Op: ir.FilterVarTypeImplementsOp, Value: op.varName, Args: args} - case "Type.HasMethod": - return ir.FilterExpr{Op: ir.FilterVarTypeHasMethodOp, Value: op.varName, Args: args} - } - } - - return ir.FilterExpr{} -} - -func (conv *converter) parseStringArg(e ast.Expr) string { - s, ok := conv.toStringValue(e) - if !ok { - panic(conv.errorf(e, "expected a string literal argument")) - } - return s -} - -func (conv *converter) toStringValue(x ast.Node) (string, bool) { - switch x := x.(type) { - case *ast.BasicLit: - if x.Kind != token.STRING { - return "", false - } - s, err := strconv.Unquote(x.Value) - if err != nil { - return "", false - } - return s, true - case ast.Expr: - typ, ok := conv.types.Types[x] - if !ok || typ.Type.String() != "string" { - return "", false - } - str := constant.StringVal(typ.Value) - return str, true - } - return "", false -} - -func (conv *converter) inspectFilterSelector(e ast.Expr) filterExprSelector { - var o filterExprSelector - - if call, ok := e.(*ast.CallExpr); ok { - o.args = call.Args - e = call.Fun - } - var path string - for { - if call, ok := e.(*ast.CallExpr); ok { - e = call.Fun - continue - } - selector, ok := e.(*ast.SelectorExpr) - if !ok { - break - } - if path == "" { - path = selector.Sel.Name - } else { - path = selector.Sel.Name + "." + path - } - e = astutil.Unparen(selector.X) - } - - o.path = path - - indexing, ok := astutil.Unparen(e).(*ast.IndexExpr) - if !ok { - return o - } - mapIdent, ok := astutil.Unparen(indexing.X).(*ast.Ident) - if !ok { - return o - } - o.mapName = mapIdent.Name - indexString, _ := conv.toStringValue(indexing.Index) - o.varName = indexString - - return o -} - -type filterExprSelector struct { - mapName string - varName string - path string - args []ast.Expr -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/libdsl.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/libdsl.go deleted file mode 100644 index d0e161613..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/libdsl.go +++ /dev/null @@ -1,401 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/types" - - "github.com/quasilyte/go-ruleguard/internal/xtypes" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" -) - -// This file implements `dsl/*` packages as native functions in quasigo. -// -// Every function and method defined in any `dsl/*` package should have -// associated Go function that implements it. -// -// In quasigo, it's impossible to have a pointer to an interface and -// non-pointer struct type. All interface type methods have FQN without `*` prefix -// while all struct type methods always begin with `*`. -// -// Fields are readonly. -// Field access is compiled into a method call that have a name identical to the field. -// For example, `foo.Bar` field access will be compiled as `foo.Bar()`. -// This may change in the future; benchmarks are needed to figure out -// what is more efficient: reflect-based field access or a function call. -// -// To keep this code organized, every type and package functions are represented -// as structs with methods. Then we bind a method value to quasigo symbol. -// The naming scheme is `dsl{$name}Package` for packages and `dsl{$pkg}{$name}` for types. - -func initEnv(state *engineState, env *quasigo.Env) { - nativeTypes := map[string]quasigoNative{ - `*github.com/quasilyte/go-ruleguard/dsl.MatchedText`: dslMatchedText{}, - `*github.com/quasilyte/go-ruleguard/dsl.DoVar`: dslDoVar{}, - `*github.com/quasilyte/go-ruleguard/dsl.DoContext`: dslDoContext{}, - `*github.com/quasilyte/go-ruleguard/dsl.VarFilterContext`: dslVarFilterContext{state: state}, - `github.com/quasilyte/go-ruleguard/dsl/types.Type`: dslTypesType{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Interface`: dslTypesInterface{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Pointer`: dslTypesPointer{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Struct`: dslTypesStruct{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Array`: dslTypesArray{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Slice`: dslTypesSlice{}, - `*github.com/quasilyte/go-ruleguard/dsl/types.Var`: dslTypesVar{}, - } - - for qualifier, typ := range nativeTypes { - for methodName, fn := range typ.funcs() { - env.AddNativeMethod(qualifier, methodName, fn) - } - } - - nativePackages := map[string]quasigoNative{ - `github.com/quasilyte/go-ruleguard/dsl/types`: dslTypesPackage{}, - } - - for qualifier, pkg := range nativePackages { - for funcName, fn := range pkg.funcs() { - env.AddNativeMethod(qualifier, funcName, fn) - } - } -} - -type quasigoNative interface { - funcs() map[string]func(*quasigo.ValueStack) -} - -type dslTypesType struct{} - -func (native dslTypesType) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - } -} - -func (dslTypesType) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(types.Type).Underlying()) -} - -func (dslTypesType) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(types.Type).String()) -} - -type dslTypesInterface struct{} - -func (native dslTypesInterface) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - } -} - -func (dslTypesInterface) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Interface).Underlying()) -} - -func (dslTypesInterface) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Interface).String()) -} - -type dslTypesSlice struct{} - -func (native dslTypesSlice) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - "Elem": native.Elem, - } -} - -func (dslTypesSlice) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Slice).Underlying()) -} - -func (dslTypesSlice) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Slice).String()) -} - -func (dslTypesSlice) Elem(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Slice).Elem()) -} - -type dslTypesArray struct{} - -func (native dslTypesArray) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - "Elem": native.Elem, - "Len": native.Len, - } -} - -func (dslTypesArray) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Array).Underlying()) -} - -func (dslTypesArray) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Array).String()) -} - -func (dslTypesArray) Elem(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Array).Elem()) -} - -func (dslTypesArray) Len(stack *quasigo.ValueStack) { - stack.PushInt(int(stack.Pop().(*types.Array).Len())) -} - -type dslTypesPointer struct{} - -func (native dslTypesPointer) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - "Elem": native.Elem, - } -} - -func (dslTypesPointer) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Pointer).Underlying()) -} - -func (dslTypesPointer) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Pointer).String()) -} - -func (dslTypesPointer) Elem(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Pointer).Elem()) -} - -type dslTypesStruct struct{} - -func (native dslTypesStruct) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Underlying": native.Underlying, - "String": native.String, - "NumFields": native.NumFields, - "Field": native.Field, - } -} - -func (dslTypesStruct) Underlying(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Struct).Underlying()) -} - -func (dslTypesStruct) String(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Struct).String()) -} - -func (dslTypesStruct) NumFields(stack *quasigo.ValueStack) { - stack.PushInt(stack.Pop().(*types.Struct).NumFields()) -} - -func (dslTypesStruct) Field(stack *quasigo.ValueStack) { - i := stack.PopInt() - typ := stack.Pop().(*types.Struct) - stack.Push(typ.Field(i)) -} - -type dslTypesPackage struct{} - -func (native dslTypesPackage) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Implements": native.Implements, - "Identical": native.Identical, - "NewArray": native.NewArray, - "NewSlice": native.NewSlice, - "NewPointer": native.NewPointer, - "AsArray": native.AsArray, - "AsSlice": native.AsSlice, - "AsPointer": native.AsPointer, - "AsInterface": native.AsInterface, - "AsStruct": native.AsStruct, - } -} - -func (dslTypesPackage) Implements(stack *quasigo.ValueStack) { - iface := stack.Pop().(*types.Interface) - typ := stack.Pop().(types.Type) - stack.Push(xtypes.Implements(typ, iface)) -} - -func (dslTypesPackage) Identical(stack *quasigo.ValueStack) { - y := stack.Pop().(types.Type) - x := stack.Pop().(types.Type) - stack.Push(xtypes.Identical(x, y)) -} - -func (dslTypesPackage) NewArray(stack *quasigo.ValueStack) { - length := stack.PopInt() - typ := stack.Pop().(types.Type) - stack.Push(types.NewArray(typ, int64(length))) -} - -func (dslTypesPackage) NewSlice(stack *quasigo.ValueStack) { - typ := stack.Pop().(types.Type) - stack.Push(types.NewSlice(typ)) -} - -func (dslTypesPackage) NewPointer(stack *quasigo.ValueStack) { - typ := stack.Pop().(types.Type) - stack.Push(types.NewPointer(typ)) -} - -func (dslTypesPackage) AsArray(stack *quasigo.ValueStack) { - typ, _ := stack.Pop().(types.Type).(*types.Array) - stack.Push(typ) -} - -func (dslTypesPackage) AsSlice(stack *quasigo.ValueStack) { - typ, _ := stack.Pop().(types.Type).(*types.Slice) - stack.Push(typ) -} - -func (dslTypesPackage) AsPointer(stack *quasigo.ValueStack) { - typ, _ := stack.Pop().(types.Type).(*types.Pointer) - stack.Push(typ) -} - -func (dslTypesPackage) AsInterface(stack *quasigo.ValueStack) { - typ, _ := stack.Pop().(types.Type).(*types.Interface) - stack.Push(typ) -} - -func (dslTypesPackage) AsStruct(stack *quasigo.ValueStack) { - typ, _ := stack.Pop().(types.Type).(*types.Struct) - stack.Push(typ) -} - -type dslTypesVar struct{} - -func (native dslTypesVar) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Embedded": native.Embedded, - "Type": native.Type, - } -} - -func (dslTypesVar) Embedded(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Var).Embedded()) -} - -func (dslTypesVar) Type(stack *quasigo.ValueStack) { - stack.Push(stack.Pop().(*types.Var).Type()) -} - -type dslDoContext struct{} - -func (native dslDoContext) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "SetReport": native.SetReport, - "SetSuggest": native.SetSuggest, - "Var": native.Var, - } -} - -func (native dslDoContext) Var(stack *quasigo.ValueStack) { - s := stack.Pop().(string) - params := stack.Pop().(*filterParams) - stack.Push(&dslDoVarRepr{params: params, name: s}) -} - -func (native dslDoContext) SetReport(stack *quasigo.ValueStack) { - s := stack.Pop().(string) - params := stack.Pop().(*filterParams) - params.reportString = s -} - -func (native dslDoContext) SetSuggest(stack *quasigo.ValueStack) { - s := stack.Pop().(string) - params := stack.Pop().(*filterParams) - params.suggestString = s -} - -type dslMatchedText struct{} - -func (native dslMatchedText) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "String": native.String, - } -} - -func (dslMatchedText) String(stack *quasigo.ValueStack) { - fmt.Printf("%T\n", stack.Pop()) - stack.Push("ok2") -} - -type dslDoVarRepr struct { - params *filterParams - name string -} - -type dslDoVar struct{} - -func (native dslDoVar) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Text": native.Text, - "Type": native.Type, - } -} - -func (dslDoVar) Text(stack *quasigo.ValueStack) { - v := stack.Pop().(*dslDoVarRepr) - params := v.params - stack.Push(params.nodeString(params.subNode(v.name))) -} - -func (dslDoVar) Type(stack *quasigo.ValueStack) { - v := stack.Pop().(*dslDoVarRepr) - params := v.params - stack.Push(params.typeofNode(params.subNode(v.name))) -} - -type dslVarFilterContext struct { - state *engineState -} - -func (native dslVarFilterContext) funcs() map[string]func(*quasigo.ValueStack) { - return map[string]func(*quasigo.ValueStack){ - "Type": native.Type, - "SizeOf": native.SizeOf, - "GetType": native.GetType, - "GetInterface": native.GetInterface, - } -} - -func (dslVarFilterContext) Type(stack *quasigo.ValueStack) { - params := stack.Pop().(*filterParams) - typ := params.typeofNode(params.subExpr(params.varname)) - stack.Push(typ) -} - -func (native dslVarFilterContext) SizeOf(stack *quasigo.ValueStack) { - typ := stack.Pop().(types.Type) - params := stack.Pop().(*filterParams) - stack.PushInt(int(params.ctx.Sizes.Sizeof(typ))) -} - -func (native dslVarFilterContext) GetType(stack *quasigo.ValueStack) { - fqn := stack.Pop().(string) - params := stack.Pop().(*filterParams) - typ, err := native.state.FindType(params.importer, params.ctx.Pkg, fqn) - if err != nil { - panic(err) - } - stack.Push(typ) -} - -func (native dslVarFilterContext) GetInterface(stack *quasigo.ValueStack) { - fqn := stack.Pop().(string) - params := stack.Pop().(*filterParams) - typ, err := native.state.FindType(params.importer, params.ctx.Pkg, fqn) - if err != nil { - panic(err) - } - if ifaceType, ok := typ.Underlying().(*types.Interface); ok { - stack.Push(ifaceType) - return - } - stack.Push((*types.Interface)(nil)) // Not found or not an interface -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/match_data.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/match_data.go deleted file mode 100644 index b0909f75f..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/match_data.go +++ /dev/null @@ -1,19 +0,0 @@ -package ruleguard - -import ( - "go/ast" - - "github.com/quasilyte/gogrep" -) - -type matchData struct { - match gogrep.MatchData -} - -func (m matchData) Node() ast.Node { return m.match.Node } - -func (m matchData) CaptureList() []gogrep.CapturedNode { return m.match.Capture } - -func (m matchData) CapturedByName(name string) (ast.Node, bool) { - return m.match.CapturedByName(name) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go deleted file mode 100644 index 4ba741ee2..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go +++ /dev/null @@ -1,49 +0,0 @@ -package ruleguard - -import ( - "fmt" - "go/ast" - "strings" -) - -type nodePath struct { - stack []ast.Node -} - -func newNodePath() *nodePath { - return &nodePath{stack: make([]ast.Node, 0, 32)} -} - -func (p nodePath) String() string { - parts := make([]string, len(p.stack)) - for i, n := range p.stack { - parts[i] = fmt.Sprintf("%T", n) - } - return strings.Join(parts, "/") -} - -func (p *nodePath) Parent() ast.Node { - return p.NthParent(1) -} - -func (p *nodePath) Current() ast.Node { - return p.NthParent(0) -} - -func (p *nodePath) NthParent(n int) ast.Node { - index := uint(len(p.stack) - n - 1) - if index < uint(len(p.stack)) { - return p.stack[index] - } - return nil -} - -func (p *nodePath) Len() int { return len(p.stack) } - -func (p *nodePath) Push(n ast.Node) { - p.stack = append(p.stack, n) -} - -func (p *nodePath) Pop() { - p.stack = p.stack[:len(p.stack)-1] -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/no_labels.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/no_labels.go deleted file mode 100644 index c5b26e230..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/no_labels.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !pproflabels -// +build !pproflabels - -package profiling - -import ( - "context" -) - -const LabelsEnabled = false - -func EnterWithLabels(origContext context.Context, name string) { -} - -func Leave(origContext context.Context) { -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/with_labels.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/with_labels.go deleted file mode 100644 index 6a35a13ad..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/profiling/with_labels.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build pproflabels -// +build pproflabels - -package profiling - -import ( - "context" - "runtime/pprof" -) - -const LabelsEnabled = true - -func EnterWithLabels(origContext context.Context, name string) { - labels := pprof.Labels("rules", name) - ctx := pprof.WithLabels(origContext, labels) - pprof.SetGoroutineLabels(ctx) -} - -func Leave(origContext context.Context) { - pprof.SetGoroutineLabels(origContext) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/compile.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/compile.go deleted file mode 100644 index 95ca9297e..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/compile.go +++ /dev/null @@ -1,869 +0,0 @@ -package quasigo - -import ( - "fmt" - "go/ast" - "go/constant" - "go/token" - "go/types" - - "github.com/quasilyte/go-ruleguard/ruleguard/goutil" - "golang.org/x/tools/go/ast/astutil" -) - -var voidType = &types.Tuple{} - -func compile(ctx *CompileContext, fn *ast.FuncDecl) (compiled *Func, err error) { - defer func() { - if err != nil { - return - } - rv := recover() - if rv == nil { - return - } - if compileErr, ok := rv.(compileError); ok { - err = compileErr - return - } - panic(rv) // not our panic - }() - - return compileFunc(ctx, fn), nil -} - -func compileFunc(ctx *CompileContext, fn *ast.FuncDecl) *Func { - cl := compiler{ - ctx: ctx, - fnType: ctx.Types.ObjectOf(fn.Name).Type().(*types.Signature), - constantsPool: make(map[interface{}]int), - intConstantsPool: make(map[int]int), - locals: make(map[string]int), - } - return cl.compileFunc(fn) -} - -type compiler struct { - ctx *CompileContext - - fnType *types.Signature - retType types.Type - - lastOp opcode - - locals map[string]int - constantsPool map[interface{}]int - intConstantsPool map[int]int - - params map[string]int - intParams map[string]int - - code []byte - constants []interface{} - intConstants []int - - breakTarget *label - continueTarget *label - - labels []*label -} - -type label struct { - targetPos int - sources []int -} - -type compileError string - -func (e compileError) Error() string { return string(e) } - -func (cl *compiler) compileFunc(fn *ast.FuncDecl) *Func { - switch cl.fnType.Results().Len() { - case 0: - cl.retType = voidType - case 1: - cl.retType = cl.fnType.Results().At(0).Type() - default: - panic(cl.errorf(fn.Name, "multi-result functions are not supported")) - } - - if !cl.isSupportedType(cl.retType) { - panic(cl.errorUnsupportedType(fn.Name, cl.retType, "function result")) - } - - cl.params = make(map[string]int, cl.fnType.Params().Len()) - cl.intParams = make(map[string]int, cl.fnType.Params().Len()) - for i := 0; i < cl.fnType.Params().Len(); i++ { - p := cl.fnType.Params().At(i) - paramName := p.Name() - paramType := p.Type() - if !cl.isSupportedType(paramType) { - panic(cl.errorUnsupportedType(fn.Name, paramType, paramName+" param")) - } - if typeIsInt(paramType) { - cl.intParams[paramName] = len(cl.intParams) - } else { - cl.params[paramName] = len(cl.params) - } - } - - dbg := funcDebugInfo{ - paramNames: make([]string, len(cl.params)), - intParamNames: make([]string, len(cl.intParams)), - } - for paramName, i := range cl.params { - dbg.paramNames[i] = paramName - } - for paramName, i := range cl.intParams { - dbg.intParamNames[i] = paramName - } - - cl.compileStmt(fn.Body) - if cl.retType == voidType { - cl.emit(opReturn) - } - - compiled := &Func{ - code: cl.code, - constants: cl.constants, - intConstants: cl.intConstants, - numObjectParams: len(cl.params), - numIntParams: len(cl.intParams), - name: cl.ctx.Package.Path() + "." + fn.Name.String(), - } - if len(cl.locals) != 0 { - dbg.localNames = make([]string, len(cl.locals)) - for localName, localIndex := range cl.locals { - dbg.localNames[localIndex] = localName - } - } - cl.ctx.Env.debug.funcs[compiled] = dbg - cl.linkJumps() - return compiled -} - -func (cl *compiler) compileStmt(stmt ast.Stmt) { - switch stmt := stmt.(type) { - case *ast.ReturnStmt: - cl.compileReturnStmt(stmt) - - case *ast.AssignStmt: - cl.compileAssignStmt(stmt) - - case *ast.IncDecStmt: - cl.compileIncDecStmt(stmt) - - case *ast.IfStmt: - cl.compileIfStmt(stmt) - - case *ast.ForStmt: - cl.compileForStmt(stmt) - - case *ast.BranchStmt: - cl.compileBranchStmt(stmt) - - case *ast.ExprStmt: - cl.compileExprStmt(stmt) - - case *ast.BlockStmt: - for i := range stmt.List { - cl.compileStmt(stmt.List[i]) - } - - default: - panic(cl.errorf(stmt, "can't compile %T yet", stmt)) - } -} - -func (cl *compiler) compileIncDecStmt(stmt *ast.IncDecStmt) { - varname, ok := stmt.X.(*ast.Ident) - if !ok { - panic(cl.errorf(stmt.X, "can assign only to simple variables")) - } - id := cl.getLocal(varname, varname.String()) - if stmt.Tok == token.INC { - cl.emit8(opIncLocal, id) - } else { - cl.emit8(opDecLocal, id) - } -} - -func (cl *compiler) compileBranchStmt(branch *ast.BranchStmt) { - if branch.Label != nil { - panic(cl.errorf(branch.Label, "can't compile %s with a label", branch.Tok)) - } - - switch branch.Tok { - case token.BREAK: - cl.emitJump(opJump, cl.breakTarget) - default: - panic(cl.errorf(branch, "can't compile %s yet", branch.Tok)) - } -} - -func (cl *compiler) compileExprStmt(stmt *ast.ExprStmt) { - if call, ok := stmt.X.(*ast.CallExpr); ok { - sig := cl.ctx.Types.TypeOf(call.Fun).(*types.Signature) - if sig.Results() != nil { - panic(cl.errorf(call, "only void funcs can be used in stmt context")) - } - cl.compileCallExpr(call) - return - } - - panic(cl.errorf(stmt.X, "can't compile this expr stmt yet: %T", stmt.X)) -} - -func (cl *compiler) compileForStmt(stmt *ast.ForStmt) { - labelBreak := cl.newLabel() - labelContinue := cl.newLabel() - prevBreakTarget := cl.breakTarget - prevContinueTarget := cl.continueTarget - cl.breakTarget = labelBreak - cl.continueTarget = labelContinue - - switch { - case stmt.Cond != nil && stmt.Init != nil && stmt.Post != nil: - // Will be implemented later; probably when the max number of locals will be lifted. - panic(cl.errorf(stmt, "can't compile C-style for loops yet")) - - case stmt.Cond != nil && stmt.Init == nil && stmt.Post == nil: - // `for { ... }` - labelBody := cl.newLabel() - cl.emitJump(opJump, labelContinue) - cl.bindLabel(labelBody) - cl.compileStmt(stmt.Body) - cl.bindLabel(labelContinue) - cl.compileExpr(stmt.Cond) - cl.emitJump(opJumpTrue, labelBody) - cl.bindLabel(labelBreak) - - default: - // `for { ... }` - cl.bindLabel(labelContinue) - cl.compileStmt(stmt.Body) - cl.emitJump(opJump, labelContinue) - cl.bindLabel(labelBreak) - } - - cl.breakTarget = prevBreakTarget - cl.continueTarget = prevContinueTarget -} - -func (cl *compiler) compileIfStmt(stmt *ast.IfStmt) { - if stmt.Else == nil { - labelEnd := cl.newLabel() - cl.compileExpr(stmt.Cond) - cl.emitJump(opJumpFalse, labelEnd) - cl.compileStmt(stmt.Body) - cl.bindLabel(labelEnd) - return - } - - labelEnd := cl.newLabel() - labelElse := cl.newLabel() - cl.compileExpr(stmt.Cond) - cl.emitJump(opJumpFalse, labelElse) - cl.compileStmt(stmt.Body) - if !cl.isUncondJump(cl.lastOp) { - cl.emitJump(opJump, labelEnd) - } - cl.bindLabel(labelElse) - cl.compileStmt(stmt.Else) - cl.bindLabel(labelEnd) -} - -func (cl *compiler) compileAssignStmt(assign *ast.AssignStmt) { - if len(assign.Rhs) != 1 { - panic(cl.errorf(assign, "only single right operand is allowed in assignments")) - } - for _, lhs := range assign.Lhs { - _, ok := lhs.(*ast.Ident) - if !ok { - panic(cl.errorf(lhs, "can assign only to simple variables")) - } - } - - rhs := assign.Rhs[0] - cl.compileExpr(rhs) - - if assign.Tok == token.DEFINE { - for i := len(assign.Lhs) - 1; i >= 0; i-- { - varname := assign.Lhs[i].(*ast.Ident) - typ := cl.ctx.Types.TypeOf(varname) - if _, ok := cl.locals[varname.String()]; ok { - panic(cl.errorf(varname, "%s variable shadowing is not allowed", varname)) - } - if !cl.isSupportedType(typ) { - panic(cl.errorUnsupportedType(varname, typ, varname.String()+" local variable")) - } - if len(cl.locals) == maxFuncLocals { - panic(cl.errorf(varname, "can't define %s: too many locals", varname)) - } - id := len(cl.locals) - cl.locals[varname.String()] = id - cl.emit8(pickOp(typeIsInt(typ), opSetIntLocal, opSetLocal), id) - } - } else { - for i := len(assign.Lhs) - 1; i >= 0; i-- { - varname := assign.Lhs[i].(*ast.Ident) - typ := cl.ctx.Types.TypeOf(varname) - id := cl.getLocal(varname, varname.String()) - cl.emit8(pickOp(typeIsInt(typ), opSetIntLocal, opSetLocal), id) - } - } -} - -func (cl *compiler) isParamName(varname string) bool { - if _, ok := cl.params[varname]; ok { - return true - } - if _, ok := cl.intParams[varname]; ok { - return true - } - return false -} - -func (cl *compiler) getLocal(v ast.Expr, varname string) int { - id, ok := cl.locals[varname] - if !ok { - if cl.isParamName(varname) { - panic(cl.errorf(v, "can't assign to %s, params are readonly", varname)) - } - panic(cl.errorf(v, "%s is not a writeable local variable", varname)) - } - return id -} - -func (cl *compiler) compileReturnStmt(ret *ast.ReturnStmt) { - if cl.retType == voidType { - cl.emit(opReturn) - return - } - - if ret.Results == nil { - panic(cl.errorf(ret, "'naked' return statements are not allowed")) - } - - switch { - case identName(ret.Results[0]) == "true": - cl.emit(opReturnTrue) - case identName(ret.Results[0]) == "false": - cl.emit(opReturnFalse) - default: - cl.compileExpr(ret.Results[0]) - typ := cl.ctx.Types.TypeOf(ret.Results[0]) - cl.emit(pickOp(typeIsInt(typ), opReturnIntTop, opReturnTop)) - } -} - -func (cl *compiler) compileExpr(e ast.Expr) { - cv := cl.ctx.Types.Types[e].Value - if cv != nil { - cl.compileConstantValue(e, cv) - return - } - - switch e := e.(type) { - case *ast.ParenExpr: - cl.compileExpr(e.X) - - case *ast.Ident: - cl.compileIdent(e) - - case *ast.SelectorExpr: - cl.compileSelectorExpr(e) - - case *ast.UnaryExpr: - switch e.Op { - case token.NOT: - cl.compileUnaryOp(opNot, e) - default: - panic(cl.errorf(e, "can't compile unary %s yet", e.Op)) - } - - case *ast.SliceExpr: - cl.compileSliceExpr(e) - - case *ast.BinaryExpr: - cl.compileBinaryExpr(e) - - case *ast.CallExpr: - cl.compileCallExpr(e) - - default: - panic(cl.errorf(e, "can't compile %T yet", e)) - } -} - -func (cl *compiler) compileSelectorExpr(e *ast.SelectorExpr) { - typ := cl.ctx.Types.TypeOf(e.X) - key := funcKey{ - name: e.Sel.String(), - qualifier: typ.String(), - } - - if funcID, ok := cl.ctx.Env.nameToNativeFuncID[key]; ok { - cl.compileExpr(e.X) - cl.emit16(opCallNative, int(funcID)) - return - } - - panic(cl.errorf(e, "can't compile %s field access", e.Sel)) -} - -func (cl *compiler) compileBinaryExpr(e *ast.BinaryExpr) { - typ := cl.ctx.Types.TypeOf(e.X) - - switch e.Op { - case token.LOR: - cl.compileOr(e) - case token.LAND: - cl.compileAnd(e) - - case token.NEQ: - switch { - case identName(e.X) == "nil": - cl.compileExpr(e.Y) - cl.emit(opIsNotNil) - case identName(e.Y) == "nil": - cl.compileExpr(e.X) - cl.emit(opIsNotNil) - case typeIsString(typ): - cl.compileBinaryOp(opNotEqString, e) - case typeIsInt(typ): - cl.compileBinaryOp(opNotEqInt, e) - default: - panic(cl.errorf(e, "!= is not implemented for %s operands", typ)) - } - case token.EQL: - switch { - case identName(e.X) == "nil": - cl.compileExpr(e.Y) - cl.emit(opIsNil) - case identName(e.Y) == "nil": - cl.compileExpr(e.X) - cl.emit(opIsNil) - case typeIsString(cl.ctx.Types.TypeOf(e.X)): - cl.compileBinaryOp(opEqString, e) - case typeIsInt(cl.ctx.Types.TypeOf(e.X)): - cl.compileBinaryOp(opEqInt, e) - default: - panic(cl.errorf(e, "== is not implemented for %s operands", typ)) - } - - case token.GTR: - cl.compileIntBinaryOp(e, opGtInt, typ) - case token.GEQ: - cl.compileIntBinaryOp(e, opGtEqInt, typ) - case token.LSS: - cl.compileIntBinaryOp(e, opLtInt, typ) - case token.LEQ: - cl.compileIntBinaryOp(e, opLtEqInt, typ) - - case token.ADD: - switch { - case typeIsString(typ): - cl.compileBinaryOp(opConcat, e) - case typeIsInt(typ): - cl.compileBinaryOp(opAdd, e) - default: - panic(cl.errorf(e, "+ is not implemented for %s operands", typ)) - } - - case token.SUB: - cl.compileIntBinaryOp(e, opSub, typ) - - default: - panic(cl.errorf(e, "can't compile binary %s yet", e.Op)) - } -} - -func (cl *compiler) compileIntBinaryOp(e *ast.BinaryExpr, op opcode, typ types.Type) { - switch { - case typeIsInt(typ): - cl.compileBinaryOp(op, e) - default: - panic(cl.errorf(e, "%s is not implemented for %s operands", e.Op, typ)) - } -} - -func (cl *compiler) compileSliceExpr(slice *ast.SliceExpr) { - if slice.Slice3 { - panic(cl.errorf(slice, "can't compile 3-index slicing")) - } - - // No need to do slicing, its no-op `s[:]`. - if slice.Low == nil && slice.High == nil { - cl.compileExpr(slice.X) - return - } - - sliceOp := opStringSlice - sliceFromOp := opStringSliceFrom - sliceToOp := opStringSliceTo - - if !typeIsString(cl.ctx.Types.TypeOf(slice.X)) { - panic(cl.errorf(slice.X, "can't compile slicing of something that is not a string")) - } - - switch { - case slice.Low == nil && slice.High != nil: - cl.compileExpr(slice.X) - cl.compileExpr(slice.High) - cl.emit(sliceToOp) - case slice.Low != nil && slice.High == nil: - cl.compileExpr(slice.X) - cl.compileExpr(slice.Low) - cl.emit(sliceFromOp) - default: - cl.compileExpr(slice.X) - cl.compileExpr(slice.Low) - cl.compileExpr(slice.High) - cl.emit(sliceOp) - } -} - -func (cl *compiler) compileBuiltinCall(fn *ast.Ident, call *ast.CallExpr) { - switch fn.Name { - case `len`: - s := call.Args[0] - cl.compileExpr(s) - if !typeIsString(cl.ctx.Types.TypeOf(s)) { - panic(cl.errorf(s, "can't compile len() with non-string argument yet")) - } - cl.emit(opStringLen) - - case `println`: - if len(call.Args) != 1 { - panic(cl.errorf(call, "only 1-arg form of println() is supported")) - } - funcName := "Print" - if typeIsInt(cl.ctx.Types.TypeOf(call.Args[0])) { - funcName = "PrintInt" - } - key := funcKey{qualifier: "builtin", name: funcName} - if !cl.compileNativeCall(key, 0, nil, call.Args) { - panic(cl.errorf(fn, "builtin.%s native func is not registered", funcName)) - } - - default: - panic(cl.errorf(fn, "can't compile %s() builtin function call yet", fn)) - } -} - -func (cl *compiler) compileCallExpr(call *ast.CallExpr) { - if id, ok := astutil.Unparen(call.Fun).(*ast.Ident); ok { - _, isBuiltin := cl.ctx.Types.ObjectOf(id).(*types.Builtin) - if isBuiltin { - cl.compileBuiltinCall(id, call) - return - } - } - - expr, fn := goutil.ResolveFunc(cl.ctx.Types, call.Fun) - if fn == nil { - panic(cl.errorf(call.Fun, "can't resolve the called function")) - } - - // TODO: just use Func.FullName as a key? - key := funcKey{name: fn.Name()} - sig := fn.Type().(*types.Signature) - if sig.Recv() != nil { - key.qualifier = sig.Recv().Type().String() - } else { - key.qualifier = fn.Pkg().Path() - } - variadic := 0 - if sig.Variadic() { - variadic = sig.Params().Len() - 1 - } - if expr != nil { - cl.compileExpr(expr) - } - if cl.compileNativeCall(key, variadic, expr, call.Args) { - return - } - if cl.compileCall(key, sig, call.Args) { - return - } - panic(cl.errorf(call.Fun, "can't compile a call to %s func", key)) -} - -func (cl *compiler) compileCall(key funcKey, sig *types.Signature, args []ast.Expr) bool { - if sig.Variadic() { - return false - } - - funcID, ok := cl.ctx.Env.nameToFuncID[key] - if !ok { - return false - } - - for _, arg := range args { - cl.compileExpr(arg) - } - - var op opcode - switch { - case sig.Results().Len() == 0: - op = opVoidCall - case typeIsInt(sig.Results().At(0).Type()): - op = opIntCall - default: - op = opCall - } - - cl.emit16(op, int(funcID)) - return true -} - -func (cl *compiler) compileNativeCall(key funcKey, variadic int, funcExpr ast.Expr, args []ast.Expr) bool { - funcID, ok := cl.ctx.Env.nameToNativeFuncID[key] - if !ok { - return false - } - - if len(args) == 1 { - // Check that it's not a f(g()) call, where g() returns - // a multi-value result; we can't compile that yet. - if call, ok := args[0].(*ast.CallExpr); ok { - results := cl.ctx.Types.TypeOf(call.Fun).(*types.Signature).Results() - if results != nil && results.Len() > 1 { - panic(cl.errorf(args[0], "can't pass tuple as a func argument")) - } - } - } - - normalArgs := args - var variadicArgs []ast.Expr - if variadic != 0 { - normalArgs = args[:variadic] - variadicArgs = args[variadic:] - } - - for _, arg := range normalArgs { - cl.compileExpr(arg) - } - if variadic != 0 { - for _, arg := range variadicArgs { - cl.compileExpr(arg) - // int-typed values should appear in the interface{}-typed - // objects slice, so we get all variadic args placed in one place. - if typeIsInt(cl.ctx.Types.TypeOf(arg)) { - cl.emit(opConvIntToIface) - } - } - if len(variadicArgs) > 255 { - panic(cl.errorf(funcExpr, "too many variadic args")) - } - // Even if len(variadicArgs) is 0, we still need to overwrite - // the old variadicLen value, so the variadic func is not confused - // by some unrelated value. - cl.emit8(opSetVariadicLen, len(variadicArgs)) - } - - cl.emit16(opCallNative, int(funcID)) - return true -} - -func (cl *compiler) compileUnaryOp(op opcode, e *ast.UnaryExpr) { - cl.compileExpr(e.X) - cl.emit(op) -} - -func (cl *compiler) compileBinaryOp(op opcode, e *ast.BinaryExpr) { - cl.compileExpr(e.X) - cl.compileExpr(e.Y) - cl.emit(op) -} - -func (cl *compiler) compileOr(e *ast.BinaryExpr) { - labelEnd := cl.newLabel() - cl.compileExpr(e.X) - cl.emit(opDup) - cl.emitJump(opJumpTrue, labelEnd) - cl.compileExpr(e.Y) - cl.bindLabel(labelEnd) -} - -func (cl *compiler) compileAnd(e *ast.BinaryExpr) { - labelEnd := cl.newLabel() - cl.compileExpr(e.X) - cl.emit(opDup) - cl.emitJump(opJumpFalse, labelEnd) - cl.compileExpr(e.Y) - cl.bindLabel(labelEnd) -} - -func (cl *compiler) compileIdent(ident *ast.Ident) { - tv := cl.ctx.Types.Types[ident] - cv := tv.Value - if cv != nil { - cl.compileConstantValue(ident, cv) - return - } - if paramIndex, ok := cl.params[ident.String()]; ok { - cl.emit8(opPushParam, paramIndex) - return - } - if paramIndex, ok := cl.intParams[ident.String()]; ok { - cl.emit8(opPushIntParam, paramIndex) - return - } - if localIndex, ok := cl.locals[ident.String()]; ok { - cl.emit8(pickOp(typeIsInt(tv.Type), opPushIntLocal, opPushLocal), localIndex) - return - } - - panic(cl.errorf(ident, "can't compile a %s (type %s) variable read", ident.String(), tv.Type)) -} - -func (cl *compiler) compileConstantValue(source ast.Expr, cv constant.Value) { - switch cv.Kind() { - case constant.Bool: - v := constant.BoolVal(cv) - if v { - cl.emit(opPushTrue) - } else { - cl.emit(opPushFalse) - } - - case constant.String: - v := constant.StringVal(cv) - id := cl.internConstant(v) - cl.emit8(opPushConst, id) - - case constant.Int: - v, exact := constant.Int64Val(cv) - if !exact { - panic(cl.errorf(source, "non-exact int value")) - } - id := cl.internIntConstant(int(v)) - cl.emit8(opPushIntConst, id) - - case constant.Complex: - panic(cl.errorf(source, "can't compile complex number constants yet")) - - case constant.Float: - panic(cl.errorf(source, "can't compile float constants yet")) - - default: - panic(cl.errorf(source, "unexpected constant %v", cv)) - } -} - -func (cl *compiler) internIntConstant(v int) int { - if id, ok := cl.intConstantsPool[v]; ok { - return id - } - id := len(cl.intConstants) - cl.intConstants = append(cl.intConstants, v) - cl.intConstantsPool[v] = id - return id -} - -func (cl *compiler) internConstant(v interface{}) int { - if _, ok := v.(int); ok { - panic("compiler error: int constant interned as interface{}") - } - if id, ok := cl.constantsPool[v]; ok { - return id - } - id := len(cl.constants) - cl.constants = append(cl.constants, v) - cl.constantsPool[v] = id - return id -} - -func (cl *compiler) linkJumps() { - for _, l := range cl.labels { - for _, jumpPos := range l.sources { - offset := l.targetPos - jumpPos - patchPos := jumpPos + 1 - put16(cl.code, patchPos, offset) - } - } -} - -func (cl *compiler) newLabel() *label { - l := &label{} - cl.labels = append(cl.labels, l) - return l -} - -func (cl *compiler) bindLabel(l *label) { - l.targetPos = len(cl.code) -} - -func (cl *compiler) emit(op opcode) { - cl.lastOp = op - cl.code = append(cl.code, byte(op)) -} - -func (cl *compiler) emitJump(op opcode, l *label) { - l.sources = append(l.sources, len(cl.code)) - cl.emit(op) - cl.code = append(cl.code, 0, 0) -} - -func (cl *compiler) emit8(op opcode, arg8 int) { - cl.emit(op) - cl.code = append(cl.code, byte(arg8)) -} - -func (cl *compiler) emit16(op opcode, arg16 int) { - cl.emit(op) - buf := make([]byte, 2) - put16(buf, 0, arg16) - cl.code = append(cl.code, buf...) -} - -func (cl *compiler) errorUnsupportedType(e ast.Node, typ types.Type, where string) compileError { - return cl.errorf(e, "%s type: %s is not supported, try something simpler", where, typ) -} - -func (cl *compiler) errorf(n ast.Node, format string, args ...interface{}) compileError { - loc := cl.ctx.Fset.Position(n.Pos()) - message := fmt.Sprintf("%s:%d: %s", loc.Filename, loc.Line, fmt.Sprintf(format, args...)) - return compileError(message) -} - -func (cl *compiler) isUncondJump(op opcode) bool { - switch op { - case opJump, opReturnFalse, opReturnTrue, opReturnTop, opReturnIntTop: - return true - default: - return false - } -} - -func (cl *compiler) isSupportedType(typ types.Type) bool { - if typ == voidType { - return true - } - - switch typ := typ.Underlying().(type) { - case *types.Pointer: - // 1. Pointers to structs are supported. - _, isStruct := typ.Elem().Underlying().(*types.Struct) - return isStruct - - case *types.Basic: - // 2. Some of the basic types are supported. - // TODO: support byte/uint8 and maybe float64. - switch typ.Kind() { - case types.Bool, types.Int, types.String: - return true - default: - return false - } - - case *types.Interface: - // 3. Interfaces are supported. - return true - - default: - return false - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/debug_info.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/debug_info.go deleted file mode 100644 index 057c02bc1..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/debug_info.go +++ /dev/null @@ -1,17 +0,0 @@ -package quasigo - -type debugInfo struct { - funcs map[*Func]funcDebugInfo -} - -type funcDebugInfo struct { - paramNames []string - intParamNames []string - localNames []string -} - -func newDebugInfo() *debugInfo { - return &debugInfo{ - funcs: make(map[*Func]funcDebugInfo), - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/disasm.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/disasm.go deleted file mode 100644 index cafc9ed5e..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/disasm.go +++ /dev/null @@ -1,84 +0,0 @@ -package quasigo - -import ( - "fmt" - "strings" -) - -// TODO(quasilyte): generate extra opcode info so we can simplify disasm function? - -func disasm(env *Env, fn *Func) string { - var out strings.Builder - - dbg, ok := env.debug.funcs[fn] - if !ok { - return "\n" - } - - code := fn.code - labels := map[int]string{} - walkBytecode(code, func(pc int, op opcode) { - switch op { - case opJumpTrue, opJumpFalse, opJump: - offset := decode16(code, pc+1) - targetPC := pc + offset - if _, ok := labels[targetPC]; !ok { - labels[targetPC] = fmt.Sprintf("L%d", len(labels)) - } - } - }) - - walkBytecode(code, func(pc int, op opcode) { - if l := labels[pc]; l != "" { - fmt.Fprintf(&out, "%s:\n", l) - } - var arg interface{} - var comment string - switch op { - case opCallNative: - id := decode16(code, pc+1) - arg = id - comment = env.nativeFuncs[id].name - case opCall, opIntCall, opVoidCall: - id := decode16(code, pc+1) - arg = id - comment = env.userFuncs[id].name - case opPushParam: - index := int(code[pc+1]) - arg = index - comment = dbg.paramNames[index] - case opPushIntParam: - index := int(code[pc+1]) - arg = index - comment = dbg.intParamNames[index] - case opSetLocal, opSetIntLocal, opPushLocal, opPushIntLocal, opIncLocal, opDecLocal: - index := int(code[pc+1]) - arg = index - comment = dbg.localNames[index] - case opSetVariadicLen: - arg = int(code[pc+1]) - case opPushConst: - arg = int(code[pc+1]) - comment = fmt.Sprintf("value=%#v", fn.constants[code[pc+1]]) - case opPushIntConst: - arg = int(code[pc+1]) - comment = fmt.Sprintf("value=%#v", fn.intConstants[code[pc+1]]) - case opJumpTrue, opJumpFalse, opJump: - offset := decode16(code, pc+1) - targetPC := pc + offset - arg = offset - comment = labels[targetPC] - } - - if comment != "" { - comment = " # " + comment - } - if arg == nil { - fmt.Fprintf(&out, " %s%s\n", op, comment) - } else { - fmt.Fprintf(&out, " %s %#v%s\n", op, arg, comment) - } - }) - - return out.String() -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/env.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/env.go deleted file mode 100644 index 0e2a450b1..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/env.go +++ /dev/null @@ -1,42 +0,0 @@ -package quasigo - -type funcKey struct { - qualifier string - name string -} - -func (k funcKey) String() string { - if k.qualifier != "" { - return k.qualifier + "." + k.name - } - return k.name -} - -type nativeFunc struct { - mappedFunc func(*ValueStack) - name string // Needed for the readable disasm -} - -func newEnv() *Env { - return &Env{ - nameToNativeFuncID: make(map[funcKey]uint16), - nameToFuncID: make(map[funcKey]uint16), - - debug: newDebugInfo(), - } -} - -func (env *Env) addNativeFunc(key funcKey, f func(*ValueStack)) { - id := len(env.nativeFuncs) - env.nativeFuncs = append(env.nativeFuncs, nativeFunc{ - mappedFunc: f, - name: key.String(), - }) - env.nameToNativeFuncID[key] = uint16(id) -} - -func (env *Env) addFunc(key funcKey, f *Func) { - id := len(env.userFuncs) - env.userFuncs = append(env.userFuncs, f) - env.nameToFuncID[key] = uint16(id) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/eval.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/eval.go deleted file mode 100644 index 311da15ad..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/eval.go +++ /dev/null @@ -1,265 +0,0 @@ -package quasigo - -import ( - "fmt" - "reflect" -) - -const maxFuncLocals = 8 - -// pop2 removes the two top stack elements and returns them. -// -// Note that it returns the popped elements in the reverse order -// to make it easier to map the order in which they were pushed. -func (s *ValueStack) pop2() (second, top interface{}) { - x := s.objects[len(s.objects)-2] - y := s.objects[len(s.objects)-1] - s.objects = s.objects[:len(s.objects)-2] - return x, y -} - -func (s *ValueStack) popInt2() (second, top int) { - x := s.ints[len(s.ints)-2] - y := s.ints[len(s.ints)-1] - s.ints = s.ints[:len(s.ints)-2] - return x, y -} - -// top returns top of the stack without popping it. -func (s *ValueStack) top() interface{} { return s.objects[len(s.objects)-1] } - -func (s *ValueStack) topInt() int { return s.ints[len(s.ints)-1] } - -// dup copies the top stack element. -// Identical to s.Push(s.Top()), but more concise. -func (s *ValueStack) dup() { s.objects = append(s.objects, s.objects[len(s.objects)-1]) } - -// discard drops the top stack element. -// Identical to s.Pop() without using the result. -func (s *ValueStack) discard() { s.objects = s.objects[:len(s.objects)-1] } - -func eval(env *EvalEnv, fn *Func, top, intTop int) CallResult { - pc := 0 - code := fn.code - stack := &env.Stack - var locals [maxFuncLocals]interface{} - var intLocals [maxFuncLocals]int - - for { - switch op := opcode(code[pc]); op { - case opPushParam: - index := int(code[pc+1]) - stack.Push(stack.objects[top+index]) - pc += 2 - case opPushIntParam: - index := int(code[pc+1]) - stack.PushInt(stack.ints[intTop+index]) - pc += 2 - - case opPushLocal: - index := code[pc+1] - stack.Push(locals[index]) - pc += 2 - case opPushIntLocal: - index := code[pc+1] - stack.PushInt(intLocals[index]) - pc += 2 - - case opSetLocal: - index := code[pc+1] - locals[index] = stack.Pop() - pc += 2 - case opSetIntLocal: - index := code[pc+1] - intLocals[index] = stack.PopInt() - pc += 2 - - case opIncLocal: - index := code[pc+1] - intLocals[index]++ - pc += 2 - case opDecLocal: - index := code[pc+1] - intLocals[index]-- - pc += 2 - - case opPop: - stack.discard() - pc++ - case opDup: - stack.dup() - pc++ - - case opPushConst: - id := code[pc+1] - stack.Push(fn.constants[id]) - pc += 2 - case opPushIntConst: - id := code[pc+1] - stack.PushInt(fn.intConstants[id]) - pc += 2 - - case opConvIntToIface: - stack.Push(stack.PopInt()) - pc++ - - case opPushTrue: - stack.Push(true) - pc++ - case opPushFalse: - stack.Push(false) - pc++ - - case opReturnTrue: - return CallResult{value: true} - case opReturnFalse: - return CallResult{value: false} - case opReturnTop: - return CallResult{value: stack.top()} - case opReturnIntTop: - return CallResult{scalarValue: uint64(stack.topInt())} - case opReturn: - return CallResult{} - - case opSetVariadicLen: - stack.variadicLen = int(code[pc+1]) - pc += 2 - case opCallNative: - id := decode16(code, pc+1) - fn := env.nativeFuncs[id].mappedFunc - fn(stack) - pc += 3 - case opCall: - id := decode16(code, pc+1) - fn := env.userFuncs[id] - result := eval(env, fn, len(stack.objects)-fn.numObjectParams, len(stack.ints)-fn.numIntParams) - stack.Push(result.Value()) - pc += 3 - case opIntCall: - id := decode16(code, pc+1) - fn := env.userFuncs[id] - result := eval(env, fn, len(stack.objects)-fn.numObjectParams, len(stack.ints)-fn.numIntParams) - stack.PushInt(result.IntValue()) - pc += 3 - case opVoidCall: - id := decode16(code, pc+1) - fn := env.userFuncs[id] - eval(env, fn, len(stack.objects)-fn.numObjectParams, len(stack.ints)-fn.numIntParams) - pc += 3 - - case opJump: - offset := decode16(code, pc+1) - pc += offset - - case opJumpFalse: - if !stack.Pop().(bool) { - offset := decode16(code, pc+1) - pc += offset - } else { - pc += 3 - } - case opJumpTrue: - if stack.Pop().(bool) { - offset := decode16(code, pc+1) - pc += offset - } else { - pc += 3 - } - - case opNot: - stack.Push(!stack.Pop().(bool)) - pc++ - - case opConcat: - x, y := stack.pop2() - stack.Push(x.(string) + y.(string)) - pc++ - - case opAdd: - x, y := stack.popInt2() - stack.PushInt(x + y) - pc++ - - case opSub: - x, y := stack.popInt2() - stack.PushInt(x - y) - pc++ - - case opEqInt: - x, y := stack.popInt2() - stack.Push(x == y) - pc++ - - case opNotEqInt: - x, y := stack.popInt2() - stack.Push(x != y) - pc++ - - case opGtInt: - x, y := stack.popInt2() - stack.Push(x > y) - pc++ - - case opGtEqInt: - x, y := stack.popInt2() - stack.Push(x >= y) - pc++ - - case opLtInt: - x, y := stack.popInt2() - stack.Push(x < y) - pc++ - - case opLtEqInt: - x, y := stack.popInt2() - stack.Push(x <= y) - pc++ - - case opEqString: - x, y := stack.pop2() - stack.Push(x.(string) == y.(string)) - pc++ - - case opNotEqString: - x, y := stack.pop2() - stack.Push(x.(string) != y.(string)) - pc++ - - case opIsNil: - x := stack.Pop() - stack.Push(x == nil || reflect.ValueOf(x).IsNil()) - pc++ - - case opIsNotNil: - x := stack.Pop() - stack.Push(x != nil && !reflect.ValueOf(x).IsNil()) - pc++ - - case opStringSlice: - to := stack.PopInt() - from := stack.PopInt() - s := stack.Pop().(string) - stack.Push(s[from:to]) - pc++ - - case opStringSliceFrom: - from := stack.PopInt() - s := stack.Pop().(string) - stack.Push(s[from:]) - pc++ - - case opStringSliceTo: - to := stack.PopInt() - s := stack.Pop().(string) - stack.Push(s[:to]) - pc++ - - case opStringLen: - stack.PushInt(len(stack.Pop().(string))) - pc++ - - default: - panic(fmt.Sprintf("malformed bytecode: unexpected %s found", op)) - } - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/gen_opcodes.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/gen_opcodes.go deleted file mode 100644 index 80386df28..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/gen_opcodes.go +++ /dev/null @@ -1,192 +0,0 @@ -//go:build main -// +build main - -package main - -import ( - "bytes" - "fmt" - "go/format" - "log" - "os" - "strings" - "text/template" -) - -var opcodePrototypes = []opcodeProto{ - {"Pop", "op", "(value) -> ()"}, - {"Dup", "op", "(x) -> (x x)"}, - - {"PushParam", "op index:u8", "() -> (value)"}, - {"PushIntParam", "op index:u8", "() -> (value:int)"}, - {"PushLocal", "op index:u8", "() -> (value)"}, - {"PushIntLocal", "op index:u8", "() -> (value:int)"}, - {"PushFalse", "op", "() -> (false)"}, - {"PushTrue", "op", "() -> (true)"}, - {"PushConst", "op constid:u8", "() -> (const)"}, - {"PushIntConst", "op constid:u8", "() -> (const:int)"}, - - {"ConvIntToIface", "op", "(value:int) -> (value)"}, - - {"SetLocal", "op index:u8", "(value) -> ()"}, - {"SetIntLocal", "op index:u8", "(value:int) -> ()"}, - {"IncLocal", "op index:u8", stackUnchanged}, - {"DecLocal", "op index:u8", stackUnchanged}, - - {"ReturnTop", "op", "(value) -> (value)"}, - {"ReturnIntTop", "op", "(value) -> (value)"}, - {"ReturnFalse", "op", stackUnchanged}, - {"ReturnTrue", "op", stackUnchanged}, - {"Return", "op", stackUnchanged}, - - {"Jump", "op offset:i16", stackUnchanged}, - {"JumpFalse", "op offset:i16", "(cond:bool) -> ()"}, - {"JumpTrue", "op offset:i16", "(cond:bool) -> ()"}, - - {"SetVariadicLen", "op len:u8", stackUnchanged}, - {"CallNative", "op funcid:u16", "(args...) -> (results...)"}, - {"Call", "op funcid:u16", "(args...) -> (result)"}, - {"IntCall", "op funcid:u16", "(args...) -> (result:int)"}, - {"VoidCall", "op funcid:u16", "(args...) -> ()"}, - - {"IsNil", "op", "(value) -> (result:bool)"}, - {"IsNotNil", "op", "(value) -> (result:bool)"}, - - {"Not", "op", "(value:bool) -> (result:bool)"}, - - {"EqInt", "op", "(x:int y:int) -> (result:bool)"}, - {"NotEqInt", "op", "(x:int y:int) -> (result:bool)"}, - {"GtInt", "op", "(x:int y:int) -> (result:bool)"}, - {"GtEqInt", "op", "(x:int y:int) -> (result:bool)"}, - {"LtInt", "op", "(x:int y:int) -> (result:bool)"}, - {"LtEqInt", "op", "(x:int y:int) -> (result:bool)"}, - - {"EqString", "op", "(x:string y:string) -> (result:bool)"}, - {"NotEqString", "op", "(x:string y:string) -> (result:bool)"}, - - {"Concat", "op", "(x:string y:string) -> (result:string)"}, - {"Add", "op", "(x:int y:int) -> (result:int)"}, - {"Sub", "op", "(x:int y:int) -> (result:int)"}, - - {"StringSlice", "op", "(s:string from:int to:int) -> (result:string)"}, - {"StringSliceFrom", "op", "(s:string from:int) -> (result:string)"}, - {"StringSliceTo", "op", "(s:string to:int) -> (result:string)"}, - {"StringLen", "op", "(s:string) -> (result:int)"}, -} - -type opcodeProto struct { - name string - enc string - stack string -} - -type encodingInfo struct { - width int - parts int -} - -type opcodeInfo struct { - Opcode byte - Name string - Enc string - EncString string - Stack string - Width int -} - -const stackUnchanged = "" - -var fileTemplate = template.Must(template.New("opcodes.go").Parse(`// Code generated "gen_opcodes.go"; DO NOT EDIT. - -package quasigo - -//go:generate stringer -type=opcode -trimprefix=op -type opcode byte - -const ( - opInvalid opcode = 0 -{{ range .Opcodes }} - // Encoding: {{.EncString}} - // Stack effect: {{ if .Stack}}{{.Stack}}{{else}}unchanged{{end}} - op{{ .Name }} opcode = {{.Opcode}} -{{ end -}} -) - -type opcodeInfo struct { - width int -} - -var opcodeInfoTable = [256]opcodeInfo{ - opInvalid: {width: 1}, - -{{ range .Opcodes -}} - op{{.Name}}: {width: {{.Width}}}, -{{ end }} -} -`)) - -func main() { - opcodes := make([]opcodeInfo, len(opcodePrototypes)) - for i, proto := range opcodePrototypes { - opcode := byte(i + 1) - encInfo := decodeEnc(proto.enc) - var encString string - if encInfo.parts == 1 { - encString = fmt.Sprintf("0x%02x (width=%d)", opcode, encInfo.width) - } else { - encString = fmt.Sprintf("0x%02x %s (width=%d)", - opcode, strings.TrimPrefix(proto.enc, "op "), encInfo.width) - } - - opcodes[i] = opcodeInfo{ - Opcode: opcode, - Name: proto.name, - Enc: proto.enc, - EncString: encString, - Stack: proto.stack, - Width: encInfo.width, - } - } - - var buf bytes.Buffer - err := fileTemplate.Execute(&buf, map[string]interface{}{ - "Opcodes": opcodes, - }) - if err != nil { - log.Panicf("execute template: %v", err) - } - writeFile("opcodes.gen.go", buf.Bytes()) -} - -func decodeEnc(enc string) encodingInfo { - fields := strings.Fields(enc) - width := 0 - for _, f := range fields { - parts := strings.Split(f, ":") - var typ string - if len(parts) == 2 { - typ = parts[1] - } else { - typ = "u8" - } - switch typ { - case "i8", "u8": - width++ - case "i16", "u16": - width += 2 - default: - panic(fmt.Sprintf("unknown op argument type: %s", typ)) - } - } - return encodingInfo{width: width, parts: len(fields)} -} - -func writeFile(filename string, data []byte) { - pretty, err := format.Source(data) - if err != nil { - log.Panicf("gofmt: %v", err) - } - if err := os.WriteFile(filename, pretty, 0666); err != nil { - log.Panicf("write %s: %v", filename, err) - } -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcode_string.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcode_string.go deleted file mode 100644 index 3136214bb..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcode_string.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by "stringer -type=opcode -trimprefix=op"; DO NOT EDIT. - -package quasigo - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[opInvalid-0] - _ = x[opPop-1] - _ = x[opDup-2] - _ = x[opPushParam-3] - _ = x[opPushIntParam-4] - _ = x[opPushLocal-5] - _ = x[opPushIntLocal-6] - _ = x[opPushFalse-7] - _ = x[opPushTrue-8] - _ = x[opPushConst-9] - _ = x[opPushIntConst-10] - _ = x[opConvIntToIface-11] - _ = x[opSetLocal-12] - _ = x[opSetIntLocal-13] - _ = x[opIncLocal-14] - _ = x[opDecLocal-15] - _ = x[opReturnTop-16] - _ = x[opReturnIntTop-17] - _ = x[opReturnFalse-18] - _ = x[opReturnTrue-19] - _ = x[opReturn-20] - _ = x[opJump-21] - _ = x[opJumpFalse-22] - _ = x[opJumpTrue-23] - _ = x[opSetVariadicLen-24] - _ = x[opCallNative-25] - _ = x[opCall-26] - _ = x[opIntCall-27] - _ = x[opVoidCall-28] - _ = x[opIsNil-29] - _ = x[opIsNotNil-30] - _ = x[opNot-31] - _ = x[opEqInt-32] - _ = x[opNotEqInt-33] - _ = x[opGtInt-34] - _ = x[opGtEqInt-35] - _ = x[opLtInt-36] - _ = x[opLtEqInt-37] - _ = x[opEqString-38] - _ = x[opNotEqString-39] - _ = x[opConcat-40] - _ = x[opAdd-41] - _ = x[opSub-42] - _ = x[opStringSlice-43] - _ = x[opStringSliceFrom-44] - _ = x[opStringSliceTo-45] - _ = x[opStringLen-46] -} - -const _opcode_name = "InvalidPopDupPushParamPushIntParamPushLocalPushIntLocalPushFalsePushTruePushConstPushIntConstConvIntToIfaceSetLocalSetIntLocalIncLocalDecLocalReturnTopReturnIntTopReturnFalseReturnTrueReturnJumpJumpFalseJumpTrueSetVariadicLenCallNativeCallIntCallVoidCallIsNilIsNotNilNotEqIntNotEqIntGtIntGtEqIntLtIntLtEqIntEqStringNotEqStringConcatAddSubStringSliceStringSliceFromStringSliceToStringLen" - -var _opcode_index = [...]uint16{0, 7, 10, 13, 22, 34, 43, 55, 64, 72, 81, 93, 107, 115, 126, 134, 142, 151, 163, 174, 184, 190, 194, 203, 211, 225, 235, 239, 246, 254, 259, 267, 270, 275, 283, 288, 295, 300, 307, 315, 326, 332, 335, 338, 349, 364, 377, 386} - -func (i opcode) String() string { - if i >= opcode(len(_opcode_index)-1) { - return "opcode(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _opcode_name[_opcode_index[i]:_opcode_index[i+1]] -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcodes.gen.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcodes.gen.go deleted file mode 100644 index a3ec270d4..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/opcodes.gen.go +++ /dev/null @@ -1,249 +0,0 @@ -// Code generated "gen_opcodes.go"; DO NOT EDIT. - -package quasigo - -//go:generate stringer -type=opcode -trimprefix=op -type opcode byte - -const ( - opInvalid opcode = 0 - - // Encoding: 0x01 (width=1) - // Stack effect: (value) -> () - opPop opcode = 1 - - // Encoding: 0x02 (width=1) - // Stack effect: (x) -> (x x) - opDup opcode = 2 - - // Encoding: 0x03 index:u8 (width=2) - // Stack effect: () -> (value) - opPushParam opcode = 3 - - // Encoding: 0x04 index:u8 (width=2) - // Stack effect: () -> (value:int) - opPushIntParam opcode = 4 - - // Encoding: 0x05 index:u8 (width=2) - // Stack effect: () -> (value) - opPushLocal opcode = 5 - - // Encoding: 0x06 index:u8 (width=2) - // Stack effect: () -> (value:int) - opPushIntLocal opcode = 6 - - // Encoding: 0x07 (width=1) - // Stack effect: () -> (false) - opPushFalse opcode = 7 - - // Encoding: 0x08 (width=1) - // Stack effect: () -> (true) - opPushTrue opcode = 8 - - // Encoding: 0x09 constid:u8 (width=2) - // Stack effect: () -> (const) - opPushConst opcode = 9 - - // Encoding: 0x0a constid:u8 (width=2) - // Stack effect: () -> (const:int) - opPushIntConst opcode = 10 - - // Encoding: 0x0b (width=1) - // Stack effect: (value:int) -> (value) - opConvIntToIface opcode = 11 - - // Encoding: 0x0c index:u8 (width=2) - // Stack effect: (value) -> () - opSetLocal opcode = 12 - - // Encoding: 0x0d index:u8 (width=2) - // Stack effect: (value:int) -> () - opSetIntLocal opcode = 13 - - // Encoding: 0x0e index:u8 (width=2) - // Stack effect: unchanged - opIncLocal opcode = 14 - - // Encoding: 0x0f index:u8 (width=2) - // Stack effect: unchanged - opDecLocal opcode = 15 - - // Encoding: 0x10 (width=1) - // Stack effect: (value) -> (value) - opReturnTop opcode = 16 - - // Encoding: 0x11 (width=1) - // Stack effect: (value) -> (value) - opReturnIntTop opcode = 17 - - // Encoding: 0x12 (width=1) - // Stack effect: unchanged - opReturnFalse opcode = 18 - - // Encoding: 0x13 (width=1) - // Stack effect: unchanged - opReturnTrue opcode = 19 - - // Encoding: 0x14 (width=1) - // Stack effect: unchanged - opReturn opcode = 20 - - // Encoding: 0x15 offset:i16 (width=3) - // Stack effect: unchanged - opJump opcode = 21 - - // Encoding: 0x16 offset:i16 (width=3) - // Stack effect: (cond:bool) -> () - opJumpFalse opcode = 22 - - // Encoding: 0x17 offset:i16 (width=3) - // Stack effect: (cond:bool) -> () - opJumpTrue opcode = 23 - - // Encoding: 0x18 len:u8 (width=2) - // Stack effect: unchanged - opSetVariadicLen opcode = 24 - - // Encoding: 0x19 funcid:u16 (width=3) - // Stack effect: (args...) -> (results...) - opCallNative opcode = 25 - - // Encoding: 0x1a funcid:u16 (width=3) - // Stack effect: (args...) -> (result) - opCall opcode = 26 - - // Encoding: 0x1b funcid:u16 (width=3) - // Stack effect: (args...) -> (result:int) - opIntCall opcode = 27 - - // Encoding: 0x1c funcid:u16 (width=3) - // Stack effect: (args...) -> () - opVoidCall opcode = 28 - - // Encoding: 0x1d (width=1) - // Stack effect: (value) -> (result:bool) - opIsNil opcode = 29 - - // Encoding: 0x1e (width=1) - // Stack effect: (value) -> (result:bool) - opIsNotNil opcode = 30 - - // Encoding: 0x1f (width=1) - // Stack effect: (value:bool) -> (result:bool) - opNot opcode = 31 - - // Encoding: 0x20 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opEqInt opcode = 32 - - // Encoding: 0x21 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opNotEqInt opcode = 33 - - // Encoding: 0x22 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opGtInt opcode = 34 - - // Encoding: 0x23 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opGtEqInt opcode = 35 - - // Encoding: 0x24 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opLtInt opcode = 36 - - // Encoding: 0x25 (width=1) - // Stack effect: (x:int y:int) -> (result:bool) - opLtEqInt opcode = 37 - - // Encoding: 0x26 (width=1) - // Stack effect: (x:string y:string) -> (result:bool) - opEqString opcode = 38 - - // Encoding: 0x27 (width=1) - // Stack effect: (x:string y:string) -> (result:bool) - opNotEqString opcode = 39 - - // Encoding: 0x28 (width=1) - // Stack effect: (x:string y:string) -> (result:string) - opConcat opcode = 40 - - // Encoding: 0x29 (width=1) - // Stack effect: (x:int y:int) -> (result:int) - opAdd opcode = 41 - - // Encoding: 0x2a (width=1) - // Stack effect: (x:int y:int) -> (result:int) - opSub opcode = 42 - - // Encoding: 0x2b (width=1) - // Stack effect: (s:string from:int to:int) -> (result:string) - opStringSlice opcode = 43 - - // Encoding: 0x2c (width=1) - // Stack effect: (s:string from:int) -> (result:string) - opStringSliceFrom opcode = 44 - - // Encoding: 0x2d (width=1) - // Stack effect: (s:string to:int) -> (result:string) - opStringSliceTo opcode = 45 - - // Encoding: 0x2e (width=1) - // Stack effect: (s:string) -> (result:int) - opStringLen opcode = 46 -) - -type opcodeInfo struct { - width int -} - -var opcodeInfoTable = [256]opcodeInfo{ - opInvalid: {width: 1}, - - opPop: {width: 1}, - opDup: {width: 1}, - opPushParam: {width: 2}, - opPushIntParam: {width: 2}, - opPushLocal: {width: 2}, - opPushIntLocal: {width: 2}, - opPushFalse: {width: 1}, - opPushTrue: {width: 1}, - opPushConst: {width: 2}, - opPushIntConst: {width: 2}, - opConvIntToIface: {width: 1}, - opSetLocal: {width: 2}, - opSetIntLocal: {width: 2}, - opIncLocal: {width: 2}, - opDecLocal: {width: 2}, - opReturnTop: {width: 1}, - opReturnIntTop: {width: 1}, - opReturnFalse: {width: 1}, - opReturnTrue: {width: 1}, - opReturn: {width: 1}, - opJump: {width: 3}, - opJumpFalse: {width: 3}, - opJumpTrue: {width: 3}, - opSetVariadicLen: {width: 2}, - opCallNative: {width: 3}, - opCall: {width: 3}, - opIntCall: {width: 3}, - opVoidCall: {width: 3}, - opIsNil: {width: 1}, - opIsNotNil: {width: 1}, - opNot: {width: 1}, - opEqInt: {width: 1}, - opNotEqInt: {width: 1}, - opGtInt: {width: 1}, - opGtEqInt: {width: 1}, - opLtInt: {width: 1}, - opLtEqInt: {width: 1}, - opEqString: {width: 1}, - opNotEqString: {width: 1}, - opConcat: {width: 1}, - opAdd: {width: 1}, - opSub: {width: 1}, - opStringSlice: {width: 1}, - opStringSliceFrom: {width: 1}, - opStringSliceTo: {width: 1}, - opStringLen: {width: 1}, -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/quasigo.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/quasigo.go deleted file mode 100644 index 8ac75771f..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/quasigo.go +++ /dev/null @@ -1,199 +0,0 @@ -// Package quasigo implements a Go subset compiler and interpreter. -// -// The implementation details are not part of the contract of this package. -package quasigo - -import ( - "go/ast" - "go/token" - "go/types" -) - -// TODO(quasilyte): document what is thread-safe and what not. -// TODO(quasilyte): add a readme. - -// Env is used to hold both compilation and evaluation data. -type Env struct { - // TODO(quasilyte): store both native and user func ids in one map? - - nativeFuncs []nativeFunc - nameToNativeFuncID map[funcKey]uint16 - - userFuncs []*Func - nameToFuncID map[funcKey]uint16 - - // debug contains all information that is only needed - // for better debugging and compiled code introspection. - // Right now it's always enabled, but we may allow stripping it later. - debug *debugInfo -} - -// EvalEnv is a goroutine-local handle for Env. -// To get one, use Env.GetEvalEnv() method. -type EvalEnv struct { - nativeFuncs []nativeFunc - userFuncs []*Func - - Stack ValueStack -} - -// NewEnv creates a new empty environment. -func NewEnv() *Env { - return newEnv() -} - -// GetEvalEnv creates a new goroutine-local handle of env. -func (env *Env) GetEvalEnv() *EvalEnv { - return &EvalEnv{ - nativeFuncs: env.nativeFuncs, - userFuncs: env.userFuncs, - Stack: ValueStack{ - objects: make([]interface{}, 0, 32), - ints: make([]int, 0, 16), - }, - } -} - -// AddNativeMethod binds `$typeName.$methodName` symbol with f. -// A typeName should be fully qualified, like `github.com/user/pkgname.TypeName`. -// It method is defined only on pointer type, the typeName should start with `*`. -func (env *Env) AddNativeMethod(typeName, methodName string, f func(*ValueStack)) { - env.addNativeFunc(funcKey{qualifier: typeName, name: methodName}, f) -} - -// AddNativeFunc binds `$pkgPath.$funcName` symbol with f. -// A pkgPath should be a full package path in which funcName is defined. -func (env *Env) AddNativeFunc(pkgPath, funcName string, f func(*ValueStack)) { - env.addNativeFunc(funcKey{qualifier: pkgPath, name: funcName}, f) -} - -// AddFunc binds `$pkgPath.$funcName` symbol with f. -func (env *Env) AddFunc(pkgPath, funcName string, f *Func) { - env.addFunc(funcKey{qualifier: pkgPath, name: funcName}, f) -} - -// GetFunc finds previously bound function searching for the `$pkgPath.$funcName` symbol. -func (env *Env) GetFunc(pkgPath, funcName string) *Func { - id := env.nameToFuncID[funcKey{qualifier: pkgPath, name: funcName}] - return env.userFuncs[id] -} - -// CompileContext is used to provide necessary data to the compiler. -type CompileContext struct { - // Env is shared environment that should be used for all functions - // being compiled; then it should be used to execute these functions. - Env *Env - - Package *types.Package - Types *types.Info - Fset *token.FileSet -} - -// Compile prepares an executable version of fn. -func Compile(ctx *CompileContext, fn *ast.FuncDecl) (compiled *Func, err error) { - return compile(ctx, fn) -} - -// Call invokes a given function. -// All arguments should be pushed to env.Stack prior to this call. -// -// Note that arguments are not popped off the stack, -// so you can bind the args once and use Call multiple times. -// If you want to reset arguments, do env.Stack.Reset(). -func Call(env *EvalEnv, fn *Func) CallResult { - numObjectArgs := len(env.Stack.objects) - numIntArgs := len(env.Stack.ints) - result := eval(env, fn, 0, 0) - env.Stack.objects = env.Stack.objects[:numObjectArgs] - env.Stack.ints = env.Stack.ints[:numIntArgs] - return result -} - -// CallResult is a return value of Call function. -// For most functions, Value() should be called to get the actual result. -// For int-typed functions, IntValue() should be used instead. -type CallResult struct { - value interface{} - scalarValue uint64 -} - -// Value unboxes an actual call return value. -// For int results, use IntValue(). -func (res CallResult) Value() interface{} { return res.value } - -// IntValue unboxes an actual call return value. -func (res CallResult) IntValue() int { return int(res.scalarValue) } - -// Disasm returns the compiled function disassembly text. -// This output is not guaranteed to be stable between versions -// and should be used only for debugging purposes. -func Disasm(env *Env, fn *Func) string { - return disasm(env, fn) -} - -// Func is a compiled function that is ready to be executed. -type Func struct { - code []byte - - constants []interface{} - intConstants []int - - numObjectParams int - numIntParams int - - name string -} - -// ValueStack is used to manipulate runtime values during the evaluation. -// Function arguments are pushed to the stack. -// Function results are returned via stack as well. -// -// For the sake of efficiency, it stores different types separately. -// If int was pushed with PushInt(), it should be retrieved by PopInt(). -// It's a bad idea to do a Push() and then PopInt() and vice-versa. -type ValueStack struct { - objects []interface{} - ints []int - variadicLen int -} - -// Reset empties the stack. -func (s *ValueStack) Reset() { - s.objects = s.objects[:0] - s.ints = s.ints[:0] -} - -// Pop removes the top stack element and returns it. -// Important: for int-typed values, use PopInt. -func (s *ValueStack) Pop() interface{} { - x := s.objects[len(s.objects)-1] - s.objects = s.objects[:len(s.objects)-1] - return x -} - -// PopInt removes the top stack element and returns it. -func (s *ValueStack) PopInt() int { - x := s.ints[len(s.ints)-1] - s.ints = s.ints[:len(s.ints)-1] - return x -} - -// PopVariadic removes the `...` argument and returns it as a slice. -// -// Slice elements are in the order they were passed to the function, -// for example, a call Sprintf("%s:%d", filename, line) returns -// the slice []interface{filename, line}. -func (s *ValueStack) PopVariadic() []interface{} { - to := len(s.objects) - from := to - s.variadicLen - xs := s.objects[from:to] - s.objects = s.objects[:from] - return xs -} - -// Push adds x to the stack. -// Important: for int-typed values, use PushInt. -func (s *ValueStack) Push(x interface{}) { s.objects = append(s.objects, x) } - -// PushInt adds x to the stack. -func (s *ValueStack) PushInt(x int) { s.ints = append(s.ints, x) } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qfmt/qfmt.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qfmt/qfmt.go deleted file mode 100644 index 249ac2563..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qfmt/qfmt.go +++ /dev/null @@ -1,17 +0,0 @@ -package qfmt - -import ( - "fmt" - - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" -) - -func ImportAll(env *quasigo.Env) { - env.AddNativeFunc(`fmt`, `Sprintf`, Sprintf) -} - -func Sprintf(stack *quasigo.ValueStack) { - args := stack.PopVariadic() - format := stack.Pop().(string) - stack.Push(fmt.Sprintf(format, args...)) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrconv/qstrconv.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrconv/qstrconv.go deleted file mode 100644 index 8bc2d943f..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrconv/qstrconv.go +++ /dev/null @@ -1,24 +0,0 @@ -package qstrconv - -import ( - "strconv" - - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" -) - -func ImportAll(env *quasigo.Env) { - env.AddNativeFunc(`strconv`, `Atoi`, Atoi) - env.AddNativeFunc(`strconv`, `Itoa`, Itoa) -} - -func Atoi(stack *quasigo.ValueStack) { - s := stack.Pop().(string) - v, err := strconv.Atoi(s) - stack.PushInt(v) - stack.Push(err) -} - -func Itoa(stack *quasigo.ValueStack) { - i := stack.PopInt() - stack.Push(strconv.Itoa(i)) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrings/qstrings.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrings/qstrings.go deleted file mode 100644 index 6b708ad9c..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/stdlib/qstrings/qstrings.go +++ /dev/null @@ -1,62 +0,0 @@ -package qstrings - -import ( - "strings" - - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" -) - -func ImportAll(env *quasigo.Env) { - env.AddNativeFunc(`strings`, `Replace`, Replace) - env.AddNativeFunc(`strings`, `ReplaceAll`, ReplaceAll) - env.AddNativeFunc(`strings`, `TrimPrefix`, TrimPrefix) - env.AddNativeFunc(`strings`, `TrimSuffix`, TrimSuffix) - env.AddNativeFunc(`strings`, `HasPrefix`, HasPrefix) - env.AddNativeFunc(`strings`, `HasSuffix`, HasSuffix) - env.AddNativeFunc(`strings`, `Contains`, Contains) -} - -func Replace(stack *quasigo.ValueStack) { - n := stack.PopInt() - newPart := stack.Pop().(string) - oldPart := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.Replace(s, oldPart, newPart, n)) -} - -func ReplaceAll(stack *quasigo.ValueStack) { - newPart := stack.Pop().(string) - oldPart := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.ReplaceAll(s, oldPart, newPart)) -} - -func TrimPrefix(stack *quasigo.ValueStack) { - prefix := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.TrimPrefix(s, prefix)) -} - -func TrimSuffix(stack *quasigo.ValueStack) { - prefix := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.TrimSuffix(s, prefix)) -} - -func HasPrefix(stack *quasigo.ValueStack) { - prefix := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.HasPrefix(s, prefix)) -} - -func HasSuffix(stack *quasigo.ValueStack) { - suffix := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.HasSuffix(s, suffix)) -} - -func Contains(stack *quasigo.ValueStack) { - substr := stack.Pop().(string) - s := stack.Pop().(string) - stack.Push(strings.Contains(s, substr)) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/utils.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/utils.go deleted file mode 100644 index a5c3676a4..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/quasigo/utils.go +++ /dev/null @@ -1,60 +0,0 @@ -package quasigo - -import ( - "encoding/binary" - "go/ast" - "go/types" -) - -func pickOp(cond bool, ifTrue, otherwise opcode) opcode { - if cond { - return ifTrue - } - return otherwise -} - -func put16(code []byte, pos, value int) { - binary.LittleEndian.PutUint16(code[pos:], uint16(value)) -} - -func decode16(code []byte, pos int) int { - return int(int16(binary.LittleEndian.Uint16(code[pos:]))) -} - -func typeIsInt(typ types.Type) bool { - basic, ok := typ.Underlying().(*types.Basic) - if !ok { - return false - } - switch basic.Kind() { - case types.Int, types.UntypedInt: - return true - default: - return false - } -} - -func typeIsString(typ types.Type) bool { - basic, ok := typ.Underlying().(*types.Basic) - if !ok { - return false - } - return basic.Info()&types.IsString != 0 -} - -func walkBytecode(code []byte, fn func(pc int, op opcode)) { - pc := 0 - for pc < len(code) { - op := opcode(code[pc]) - fn(pc, op) - pc += opcodeInfoTable[op].width - } -} - -func identName(n ast.Expr) string { - id, ok := n.(*ast.Ident) - if ok { - return id.Name - } - return "" -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go deleted file mode 100644 index 41fbc8995..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go +++ /dev/null @@ -1,221 +0,0 @@ -package ruleguard - -import ( - "go/ast" - "go/build" - "go/token" - "go/types" - "io" - - "github.com/quasilyte/go-ruleguard/ruleguard/ir" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" - "github.com/quasilyte/gogrep" -) - -// Engine is the main ruleguard package API object. -// -// First, load some ruleguard files with Load() to build a rule set. -// Then use Run() to execute the rules. -// -// It's advised to have only 1 engine per application as it does a lot of caching. -// The Run() method is synchronized, so it can be used concurrently. -// -// An Engine must be created with NewEngine() function. -type Engine struct { - impl *engine - - // BuildContext can be used as an override for build.Default context. - // Used during the Go packages resolving. - // - // Use Engine.InferBuildContext() to create a sensible default - // for this field that is better than build.Default. - // We're not using this by default to avoid the excessive work - // if you already have a properly initialized build.Context object. - // - // nil will result in build.Default usage. - BuildContext *build.Context -} - -// NewEngine creates an engine with empty rule set. -func NewEngine() *Engine { - return &Engine{impl: newEngine()} -} - -func (e *Engine) InferBuildContext() { - e.BuildContext = inferBuildContext() -} - -// Load reads a ruleguard file from r and adds it to the engine rule set. -// -// Load() is not thread-safe, especially if used concurrently with Run() method. -// It's advised to Load() all ruleguard files under a critical section (like sync.Once) -// and then use Run() to execute all of them. -func (e *Engine) Load(ctx *LoadContext, filename string, r io.Reader) error { - return e.impl.Load(ctx, e.BuildContext, filename, r) -} - -// LoadFromIR is like Load(), but it takes already parsed IR file as an input. -// -// This method can be useful if you're trying to embed a precompiled rules file -// into your binary. -func (e *Engine) LoadFromIR(ctx *LoadContext, filename string, f *ir.File) error { - return e.impl.LoadFromIR(ctx, e.BuildContext, filename, f) -} - -// LoadedGroups returns information about all currently loaded rule groups. -func (e *Engine) LoadedGroups() []GoRuleGroup { - return e.impl.LoadedGroups() -} - -// Run executes all loaded rules on a given file. -// Matched rules invoke `RunContext.Report()` method. -// -// Run() is thread-safe, unless used in parallel with Load(), -// which modifies the engine state. -func (e *Engine) Run(ctx *RunContext, f *ast.File) error { - return e.impl.Run(ctx, e.BuildContext, f) -} - -type LoadContext struct { - DebugFunc string - DebugImports bool - DebugPrint func(string) - - // GroupFilter is called for every rule group being parsed. - // If function returns false, that group will not be included - // in the resulting rules set. - // Nil filter accepts all rule groups. - GroupFilter func(*GoRuleGroup) bool - - Fset *token.FileSet -} - -type RunnerState struct { - gogrepState gogrep.MatcherState - gogrepSubState gogrep.MatcherState - nodePath *nodePath - evalEnv *quasigo.EvalEnv - typematchState *typematch.MatcherState - - object *rulesRunner -} - -// NewRunnerState creates a state object that can be used with RunContext. -func NewRunnerState(e *Engine) *RunnerState { - return newRunnerState(e.impl.state) -} - -type RunContext struct { - Debug string - DebugImports bool - DebugPrint func(string) - - Types *types.Info - Sizes types.Sizes - Fset *token.FileSet - Pkg *types.Package - - // Report is a function that is called for every successful ruleguard match. - // The pointer to ReportData is reused, it should not be kept. - // If you want to keep it after Report() returns, make a copy. - Report func(*ReportData) - - GoVersion GoVersion - - // TruncateLen is a length threshold (in bytes) for interpolated vars in Report() templates. - // - // Truncation removes the part of the string in the middle and replaces it with <...> - // so it meets the max length constraint. - // - // The default value is 60 (implied if value is 0). - // - // Note that this value is ignored for Suggest templates. - // Ruleguard doesn't truncate suggested replacement candidates. - TruncateLen int - - // State is an object that contains reusable resources needed for the rules to be executed. - // - // If nil, a new state will be allocated. - // - // The State object access is not synchronized. - // State should not be shared between multiple goroutines. - // There are 3 patterns that are safe: - // 1. For single-threaded programs, you can use a single state. - // 2. For controlled concurrency with workers, you can use a per-worker state. - // 3. For uncontrolled concurrency you can use a sync.Pool of states. - // - // Reusing the state properly can increase the performance significantly. - State *RunnerState -} - -type ReportData struct { - RuleInfo GoRuleInfo - Node ast.Node - Message string - Suggestion *Suggestion - - // Experimental: fields below are part of the experiment. - // They'll probably be removed or changed over time. - - Func *ast.FuncDecl -} - -type Suggestion struct { - From token.Pos - To token.Pos - Replacement []byte -} - -type GoRuleInfo struct { - // Line is a line inside a file that defined this rule. - Line int - - // Group is a function that contains this rule. - Group *GoRuleGroup -} - -type GoRuleGroup struct { - // Name is a function name associated with this rule group. - Name string - - // Pos is a location where this rule group was defined. - Pos token.Position - - // Line is a source code line number inside associated file. - // A pair of Filename:Line form a conventional location string. - Line int - - // Filename is a file that defined this rule group. - Filename string - - // DocTags contains a list of keys from the `gorules:tags` comment. - DocTags []string - - // DocSummary is a short one sentence description. - // Filled from the `doc:summary` pragma content. - DocSummary string - - // DocBefore is a code snippet of code that will violate rule. - // Filled from the `doc:before` pragma content. - DocBefore string - - // DocAfter is a code snippet of fixed code that complies to the rule. - // Filled from the `doc:after` pragma content. - DocAfter string - - // DocNote is an optional caution message or advice. - // Usually, it's used to reference some external resource, like - // issue on the GitHub. - // Filled from the `doc:note` pragma content. - DocNote string -} - -// ImportError is returned when a ruleguard file references a package that cannot be imported. -type ImportError struct { - msg string - err error -} - -func (e *ImportError) Error() string { return e.msg } -func (e *ImportError) Unwrap() error { return e.err } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go deleted file mode 100644 index fdc95ab5e..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go +++ /dev/null @@ -1,562 +0,0 @@ -package ruleguard - -import ( - "bytes" - "context" - "fmt" - "go/ast" - "go/build" - "go/printer" - "go/token" - "os" - "path/filepath" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/quasilyte/go-ruleguard/ruleguard/goutil" - "github.com/quasilyte/go-ruleguard/ruleguard/profiling" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" - "github.com/quasilyte/gogrep" - "github.com/quasilyte/gogrep/nodetag" -) - -type rulesRunner struct { - state *engineState - - bgContext context.Context - - ctx *RunContext - rules *goRuleSet - - truncateLen int - - reportData ReportData - - gogrepState gogrep.MatcherState - gogrepSubState gogrep.MatcherState - - importer *goImporter - - filename string - src []byte - - // nodePath is a stack of ast.Nodes we visited to this point. - // When we enter a new node, it's placed on the top of the stack. - // When we leave that node, it's popped. - // The stack is a slice that is allocated only once and reused - // for the lifetime of the runner. - // The only overhead it has is a slice append and pop operations - // that are quire cheap. - // - // Note: we need this path to get a Node.Parent() for `$$` matches. - // So it's used to climb up the tree there. - // For named submatches we can't use it as the node can be located - // deeper into the tree than the current node. - // In those cases we need a more complicated algorithm. - nodePath *nodePath - - filterParams filterParams -} - -func newRunnerState(es *engineState) *RunnerState { - gogrepState := gogrep.NewMatcherState() - gogrepSubState := gogrep.NewMatcherState() - state := &RunnerState{ - gogrepState: gogrepState, - gogrepSubState: gogrepSubState, - nodePath: newNodePath(), - evalEnv: es.env.GetEvalEnv(), - typematchState: typematch.NewMatcherState(), - object: &rulesRunner{}, - } - return state -} - -func (state *RunnerState) Reset() { - state.nodePath.stack = state.nodePath.stack[:0] - state.evalEnv.Stack.Reset() -} - -func newRulesRunner(ctx *RunContext, buildContext *build.Context, state *engineState, rules *goRuleSet) *rulesRunner { - runnerState := ctx.State - if runnerState == nil { - runnerState = newRunnerState(state) - } else { - runnerState.Reset() - } - - importer := newGoImporter(state, goImporterConfig{ - fset: ctx.Fset, - debugImports: ctx.DebugImports, - debugPrint: ctx.DebugPrint, - buildContext: buildContext, - }) - gogrepState := runnerState.gogrepState - gogrepState.Types = ctx.Types - gogrepSubState := runnerState.gogrepSubState - gogrepSubState.Types = ctx.Types - evalEnv := runnerState.evalEnv - - rr := runnerState.object - *rr = rulesRunner{ - bgContext: context.Background(), - ctx: ctx, - importer: importer, - rules: rules, - gogrepState: gogrepState, - gogrepSubState: gogrepSubState, - nodePath: runnerState.nodePath, - truncateLen: ctx.TruncateLen, - filterParams: filterParams{ - typematchState: runnerState.typematchState, - env: evalEnv, - importer: importer, - ctx: ctx, - }, - } - - evalEnv.Stack.Push(&rr.filterParams) - if ctx.TruncateLen == 0 { - rr.truncateLen = 60 - } - rr.filterParams.nodeText = rr.nodeText - rr.filterParams.nodeString = rr.nodeString - rr.filterParams.nodePath = rr.nodePath - rr.filterParams.gogrepSubState = &rr.gogrepSubState - - return rr -} - -func (rr *rulesRunner) nodeString(n ast.Node) string { - b := rr.nodeText(n) - return string(b) -} - -func (rr *rulesRunner) nodeText(n ast.Node) []byte { - if gogrep.IsEmptyNodeSlice(n) { - return nil - } - - from := rr.ctx.Fset.Position(n.Pos()).Offset - to := rr.ctx.Fset.Position(n.End()).Offset - src := rr.fileBytes() - if (from >= 0 && from < len(src)) && (to >= 0 && to < len(src)) { - return src[from:to] - } - - // Go printer would panic on comments. - if n, ok := n.(*ast.Comment); ok { - return []byte(n.Text) - } - - // Fallback to the printer. - var buf bytes.Buffer - if err := printer.Fprint(&buf, rr.ctx.Fset, n); err != nil { - panic(err) - } - return buf.Bytes() -} - -func (rr *rulesRunner) fileBytes() []byte { - if rr.src != nil { - return rr.src - } - - // TODO(quasilyte): re-use src slice? - src, err := os.ReadFile(rr.filename) - if err != nil || src == nil { - // Assign a zero-length slice so rr.src - // is never nil during the second fileBytes call. - rr.src = make([]byte, 0) - } else { - rr.src = src - } - return rr.src -} - -func (rr *rulesRunner) run(f *ast.File) error { - // If it's not empty then we're leaking memory. - // For every Push() there should be a Pop() call. - if rr.nodePath.Len() != 0 { - panic("internal error: node path is not empty") - } - - rr.filename = rr.ctx.Fset.Position(f.Pos()).Filename - rr.filterParams.filename = rr.filename - rr.collectImports(f) - - if rr.rules.universal.categorizedNum != 0 { - var inspector astWalker - inspector.nodePath = rr.nodePath - inspector.filterParams = &rr.filterParams - inspector.Walk(f, func(n ast.Node, tag nodetag.Value) { - rr.runRules(n, tag) - }) - } - - if len(rr.rules.universal.commentRules) != 0 { - for _, commentGroup := range f.Comments { - for _, comment := range commentGroup.List { - rr.runCommentRules(comment) - } - } - } - - return nil -} - -func (rr *rulesRunner) runCommentRules(comment *ast.Comment) { - // We'll need that file to create a token.Pos from the artificial offset. - file := rr.ctx.Fset.File(comment.Pos()) - - for _, rule := range rr.rules.universal.commentRules { - var m matchData - if rule.captureGroups { - result := rule.pat.FindStringSubmatchIndex(comment.Text) - if result == nil { - continue - } - for i, name := range rule.pat.SubexpNames() { - if i == 0 || name == "" { - continue - } - resultIndex := i * 2 - beginPos := result[resultIndex+0] - endPos := result[resultIndex+1] - // Negative index a special case when named group captured nothing. - // Consider this pattern: `(?Pfoo)|(bar)`. - // If we have `bar` input string, will remain empty. - if beginPos < 0 || endPos < 0 { - m.match.Capture = append(m.match.Capture, gogrep.CapturedNode{ - Name: name, - Node: &ast.Comment{Slash: comment.Pos()}, - }) - continue - } - m.match.Capture = append(m.match.Capture, gogrep.CapturedNode{ - Name: name, - Node: &ast.Comment{ - Slash: file.Pos(beginPos + file.Offset(comment.Pos())), - Text: comment.Text[beginPos:endPos], - }, - }) - } - m.match.Node = &ast.Comment{ - Slash: file.Pos(result[0] + file.Offset(comment.Pos())), - Text: comment.Text[result[0]:result[1]], - } - } else { - // Fast path: no need to save any submatches. - result := rule.pat.FindStringIndex(comment.Text) - if result == nil { - continue - } - m.match.Node = &ast.Comment{ - Slash: file.Pos(result[0] + file.Offset(comment.Pos())), - Text: comment.Text[result[0]:result[1]], - } - } - - accept := rr.handleCommentMatch(rule, m) - if accept { - break - } - } -} - -func (rr *rulesRunner) runRules(n ast.Node, tag nodetag.Value) { - // profiling.LabelsEnabled is constant, so labels-related - // code should be a no-op inside normal build. - // To enable labels, use "-tags pproflabels" build tag. - - for _, rule := range rr.rules.universal.rulesByTag[tag] { - if profiling.LabelsEnabled { - profiling.EnterWithLabels(rr.bgContext, rule.group.Name) - } - - matched := false - rule.pat.MatchNode(&rr.gogrepState, n, func(m gogrep.MatchData) { - matched = rr.handleMatch(rule, m) - }) - - if profiling.LabelsEnabled { - profiling.Leave(rr.bgContext) - } - - if matched && !multiMatchTags[tag] { - break - } - } -} - -func (rr *rulesRunner) reject(rule goRule, reason string, m matchData) { - if rule.group.Name != rr.ctx.Debug { - return // This rule is not being debugged - } - - pos := rr.ctx.Fset.Position(m.Node().Pos()) - rr.ctx.DebugPrint(fmt.Sprintf("%s:%d: [%s:%d] rejected by %s", - pos.Filename, pos.Line, filepath.Base(rule.group.Filename), rule.line, reason)) - - values := make([]gogrep.CapturedNode, len(m.CaptureList())) - copy(values, m.CaptureList()) - sort.Slice(values, func(i, j int) bool { - return values[i].Name < values[j].Name - }) - - for _, v := range values { - name := v.Name - node := v.Node - - if comment, ok := node.(*ast.Comment); ok { - s := strings.ReplaceAll(comment.Text, "\n", `\n`) - rr.ctx.DebugPrint(fmt.Sprintf(" $%s: %s", name, s)) - continue - } - - var expr ast.Expr - switch node := node.(type) { - case ast.Expr: - expr = node - case *ast.ExprStmt: - expr = node.X - default: - continue - } - - typ := rr.ctx.Types.TypeOf(expr) - typeString := "" - if typ != nil { - typeString = typ.String() - } - s := strings.ReplaceAll(goutil.SprintNode(rr.ctx.Fset, expr), "\n", `\n`) - rr.ctx.DebugPrint(fmt.Sprintf(" $%s %s: %s", name, typeString, s)) - } -} - -func (rr *rulesRunner) handleCommentMatch(rule goCommentRule, m matchData) bool { - if rule.base.filter.fn != nil { - rr.filterParams.match = m - filterResult := rule.base.filter.fn(&rr.filterParams) - if !filterResult.Matched() { - rr.reject(rule.base, filterResult.RejectReason(), m) - return false - } - } - - message := rr.renderMessage(rule.base.msg, m, true) - node := m.Node() - if rule.base.location != "" { - node, _ = m.CapturedByName(rule.base.location) - } - var suggestion *Suggestion - if rule.base.suggestion != "" { - suggestion = &Suggestion{ - Replacement: []byte(rr.renderMessage(rule.base.suggestion, m, false)), - From: node.Pos(), - To: node.End(), - } - } - info := GoRuleInfo{ - Group: rule.base.group, - Line: rule.base.line, - } - rr.reportData.RuleInfo = info - rr.reportData.Node = node - rr.reportData.Message = message - rr.reportData.Suggestion = suggestion - - rr.ctx.Report(&rr.reportData) - return true -} - -func (rr *rulesRunner) handleMatch(rule goRule, m gogrep.MatchData) bool { - if rule.filter.fn != nil || rule.do != nil { - rr.filterParams.match = matchData{match: m} - } - - if rule.filter.fn != nil { - filterResult := rule.filter.fn(&rr.filterParams) - if !filterResult.Matched() { - rr.reject(rule, filterResult.RejectReason(), matchData{match: m}) - return false - } - } - - node := m.Node - if rule.location != "" { - node, _ = m.CapturedByName(rule.location) - } - - var messageText string - var suggestText string - if rule.do != nil { - rr.filterParams.reportString = "" - rr.filterParams.suggestString = "" - _ = quasigo.Call(rr.filterParams.env, rule.do) - messageText = rr.filterParams.reportString - if messageText == "" { - if rr.filterParams.suggestString != "" { - messageText = "suggestion: " + rr.filterParams.suggestString - } else { - messageText = "" - } - } - if rr.filterParams.suggestString != "" { - suggestText = rr.filterParams.suggestString - } - } else { - messageText = rr.renderMessage(rule.msg, matchData{match: m}, true) - if rule.suggestion != "" { - suggestText = rr.renderMessage(rule.suggestion, matchData{match: m}, false) - } - } - - var suggestion *Suggestion - if suggestText != "" { - suggestion = &Suggestion{ - Replacement: []byte(suggestText), - From: node.Pos(), - To: node.End(), - } - } - - info := GoRuleInfo{ - Group: rule.group, - Line: rule.line, - } - rr.reportData.RuleInfo = info - rr.reportData.Node = node - rr.reportData.Message = messageText - rr.reportData.Suggestion = suggestion - - rr.reportData.Func = rr.filterParams.currentFunc - - rr.ctx.Report(&rr.reportData) - return true -} - -func (rr *rulesRunner) collectImports(f *ast.File) { - rr.filterParams.imports = make(map[string]struct{}, len(f.Imports)) - for _, spec := range f.Imports { - s, err := strconv.Unquote(spec.Path.Value) - if err != nil { - continue - } - rr.filterParams.imports[s] = struct{}{} - } -} - -func (rr *rulesRunner) renderMessage(msg string, m matchData, truncate bool) string { - if !strings.Contains(msg, "$") { - return msg - } - - var capture []gogrep.CapturedNode - if len(m.CaptureList()) != 0 { - capture = make([]gogrep.CapturedNode, 0, len(m.CaptureList())) - for _, c := range m.CaptureList() { - n := c.Node - // Some captured nodes are typed, but nil. - // We can't really get their text, so skip them here. - // For example, pattern `func $_() $results { $*_ }` may - // match a nil *ast.FieldList for $results if executed - // against a function with no results. - if reflect.ValueOf(n).IsNil() && !gogrep.IsEmptyNodeSlice(n) { - continue - } - capture = append(capture, c) - } - if len(capture) > 1 { - sort.Slice(capture, func(i, j int) bool { - return len(capture[i].Name) > len(capture[j].Name) - }) - } - } - - result := make([]byte, 0, len(msg)*2) - i := 0 - for { - j := strings.IndexByte(msg[i:], '$') - if j == -1 { - result = append(result, msg[i:]...) - break - } - dollarPos := i + j - result = append(result, msg[i:dollarPos]...) - var n ast.Node - var nameLen int - if strings.HasPrefix(msg[dollarPos+1:], "$") { - n = m.Node() - nameLen = 1 - } else { - for _, c := range capture { - if strings.HasPrefix(msg[dollarPos+1:], c.Name) { - n = c.Node - nameLen = len(c.Name) - break - } - } - } - if n != nil { - text := rr.nodeText(n) - text = rr.fixedText(text, n, msg[dollarPos+1+nameLen:]) - if truncate { - text = truncateText(text, rr.truncateLen) - } - result = append(result, text...) - } else { - result = append(result, '$') - } - i = dollarPos + len("$") + nameLen - } - - return string(result) -} - -func (rr *rulesRunner) fixedText(text []byte, n ast.Node, following string) []byte { - // pattern=`$x.y` $x=`&buf` following=`.y` - // Insert $x as `buf`, so we get `buf.y` instead of incorrect `&buf.y`. - if n, ok := n.(*ast.UnaryExpr); ok && n.Op == token.AND { - shouldFix := false - switch n.X.(type) { - case *ast.Ident, *ast.IndexExpr, *ast.SelectorExpr: - shouldFix = true - } - if shouldFix && strings.HasPrefix(following, ".") { - return bytes.TrimPrefix(text, []byte("&")) - } - } - - return text -} - -var longTextPlaceholder = []byte("<...>") - -func truncateText(s []byte, maxLen int) []byte { - if len(s) <= maxLen-len(longTextPlaceholder) { - return s - } - maxLen -= len(longTextPlaceholder) - leftLen := maxLen / 2 - rightLen := (maxLen % 2) + leftLen - left := s[:leftLen] - right := s[len(s)-rightLen:] - - result := make([]byte, 0, len(left)+len(longTextPlaceholder)+len(right)) - result = append(result, left...) - result = append(result, longTextPlaceholder...) - result = append(result, right...) - - return result -} - -var multiMatchTags = [nodetag.NumBuckets]bool{ - nodetag.BlockStmt: true, - nodetag.CaseClause: true, - nodetag.CommClause: true, - nodetag.File: true, -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go deleted file mode 100644 index d320bf880..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go +++ /dev/null @@ -1,84 +0,0 @@ -package textmatch - -import ( - "regexp" - "regexp/syntax" - "unicode" -) - -func compile(s string) (Pattern, error) { - reSyntax, err := syntax.Parse(s, syntax.Perl) - if err == nil { - if optimized := compileOptimized(s, reSyntax); optimized != nil { - return optimized, nil - } - } - return regexp.Compile(s) -} - -func compileOptimized(s string, re *syntax.Regexp) Pattern { - // .* - isAny := func(re *syntax.Regexp) bool { - return re.Op == syntax.OpStar && re.Sub[0].Op == syntax.OpAnyCharNotNL - } - // "literal" - isLit := func(re *syntax.Regexp) bool { - return re.Op == syntax.OpLiteral - } - // ^ - isBegin := func(re *syntax.Regexp) bool { - return re.Op == syntax.OpBeginText - } - // $ - isEnd := func(re *syntax.Regexp) bool { - return re.Op == syntax.OpEndText - } - - // TODO: analyze what kind of regexps people use in rules - // more often and optimize those as well. - - // lit => strings.Contains($input, lit) - if re.Op == syntax.OpLiteral { - return &containsLiteralMatcher{value: newInputValue(string(re.Rune))} - } - - // `.*` lit `.*` => strings.Contains($input, lit) - if re.Op == syntax.OpConcat && len(re.Sub) == 3 { - if isAny(re.Sub[0]) && isLit(re.Sub[1]) && isAny(re.Sub[2]) { - return &containsLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} - } - } - - // `^` lit => strings.HasPrefix($input, lit) - if re.Op == syntax.OpConcat && len(re.Sub) == 2 { - if isBegin(re.Sub[0]) && isLit(re.Sub[1]) { - return &prefixLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} - } - } - - // lit `$` => strings.HasSuffix($input, lit) - if re.Op == syntax.OpConcat && len(re.Sub) == 2 { - if isLit(re.Sub[0]) && isEnd(re.Sub[1]) { - return &suffixLiteralMatcher{value: newInputValue(string(re.Sub[0].Rune))} - } - } - - // `^` lit `$` => $input == lit - if re.Op == syntax.OpConcat && len(re.Sub) == 3 { - if isBegin(re.Sub[0]) && isLit(re.Sub[1]) && isEnd(re.Sub[2]) { - return &eqLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} - } - } - - // `^\p{Lu}` => prefixRunePredMatcher:unicode.IsUpper - // `^\p{Ll}` => prefixRunePredMatcher:unicode.IsLower - switch s { - case `^\p{Lu}`: - return &prefixRunePredMatcher{pred: unicode.IsUpper} - case `^\p{Ll}`: - return &prefixRunePredMatcher{pred: unicode.IsLower} - } - - // Can't optimize. - return nil -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go deleted file mode 100644 index 2f68c9aee..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go +++ /dev/null @@ -1,72 +0,0 @@ -package textmatch - -import ( - "bytes" - "strings" - "unicode/utf8" -) - -// inputValue is a wrapper for string|[]byte. -// -// We hold both values to avoid string->[]byte and vice versa -// conversions when doing Match and MatchString. -type inputValue struct { - s string - b []byte -} - -func newInputValue(s string) inputValue { - return inputValue{s: s, b: []byte(s)} -} - -type containsLiteralMatcher struct{ value inputValue } - -func (m *containsLiteralMatcher) MatchString(s string) bool { - return strings.Contains(s, m.value.s) -} - -func (m *containsLiteralMatcher) Match(b []byte) bool { - return bytes.Contains(b, m.value.b) -} - -type prefixLiteralMatcher struct{ value inputValue } - -func (m *prefixLiteralMatcher) MatchString(s string) bool { - return strings.HasPrefix(s, m.value.s) -} - -func (m *prefixLiteralMatcher) Match(b []byte) bool { - return bytes.HasPrefix(b, m.value.b) -} - -type suffixLiteralMatcher struct{ value inputValue } - -func (m *suffixLiteralMatcher) MatchString(s string) bool { - return strings.HasSuffix(s, m.value.s) -} - -func (m *suffixLiteralMatcher) Match(b []byte) bool { - return bytes.HasSuffix(b, m.value.b) -} - -type eqLiteralMatcher struct{ value inputValue } - -func (m *eqLiteralMatcher) MatchString(s string) bool { - return m.value.s == s -} - -func (m *eqLiteralMatcher) Match(b []byte) bool { - return bytes.Equal(m.value.b, b) -} - -type prefixRunePredMatcher struct{ pred func(rune) bool } - -func (m *prefixRunePredMatcher) MatchString(s string) bool { - r, _ := utf8.DecodeRuneInString(s) - return m.pred(r) -} - -func (m *prefixRunePredMatcher) Match(b []byte) bool { - r, _ := utf8.DecodeRune(b) - return m.pred(r) -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go deleted file mode 100644 index 135f95740..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go +++ /dev/null @@ -1,26 +0,0 @@ -package textmatch - -import "regexp" - -// Pattern is a compiled regular expression. -type Pattern interface { - MatchString(s string) bool - Match(b []byte) bool -} - -// Compile parses a regular expression and returns a compiled -// pattern that can match inputs described by the regexp. -// -// Semantically it's close to the regexp.Compile, but -// it does recognize some common patterns and creates -// a more optimized matcher for them. -func Compile(re string) (Pattern, error) { - return compile(re) -} - -// IsRegexp reports whether p is implemented using regexp. -// False means that the underlying matcher is something optimized. -func IsRegexp(p Pattern) bool { - _, ok := p.(*regexp.Regexp) - return ok -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go deleted file mode 100644 index 672b6b45b..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go +++ /dev/null @@ -1,36 +0,0 @@ -// Code generated by "stringer -type=patternOp"; DO NOT EDIT. - -package typematch - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[opBuiltinType-0] - _ = x[opPointer-1] - _ = x[opVar-2] - _ = x[opVarSeq-3] - _ = x[opSlice-4] - _ = x[opArray-5] - _ = x[opMap-6] - _ = x[opChan-7] - _ = x[opFuncNoSeq-8] - _ = x[opFunc-9] - _ = x[opStructNoSeq-10] - _ = x[opStruct-11] - _ = x[opAnyInterface-12] - _ = x[opNamed-13] -} - -const _patternOp_name = "opBuiltinTypeopPointeropVaropVarSeqopSliceopArrayopMapopChanopFuncNoSeqopFuncopStructNoSeqopStructopAnyInterfaceopNamed" - -var _patternOp_index = [...]uint8{0, 13, 22, 27, 35, 42, 49, 54, 60, 71, 77, 90, 98, 112, 119} - -func (i patternOp) String() string { - if i < 0 || i >= patternOp(len(_patternOp_index)-1) { - return "patternOp(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _patternOp_name[_patternOp_index[i]:_patternOp_index[i+1]] -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go deleted file mode 100644 index 4b740b207..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go +++ /dev/null @@ -1,607 +0,0 @@ -package typematch - -import ( - "fmt" - "go/ast" - "go/parser" - "go/token" - "go/types" - "strconv" - "strings" - - "github.com/quasilyte/go-ruleguard/internal/xtypes" -) - -//go:generate stringer -type=patternOp -type patternOp int - -const ( - opBuiltinType patternOp = iota - opPointer - opVar - opVarSeq - opSlice - opArray - opMap - opChan - opFuncNoSeq - opFunc - opStructNoSeq - opStruct - opAnyInterface - opNamed -) - -type MatcherState struct { - typeMatches map[string]types.Type - int64Matches map[string]int64 -} - -func NewMatcherState() *MatcherState { - return &MatcherState{ - typeMatches: map[string]types.Type{}, - int64Matches: map[string]int64{}, - } -} - -func (state *MatcherState) reset() { - if len(state.int64Matches) != 0 { - for k := range state.int64Matches { - delete(state.int64Matches, k) - } - } - if len(state.typeMatches) != 0 { - for k := range state.typeMatches { - delete(state.typeMatches, k) - } - } -} - -type Pattern struct { - root *pattern -} - -type pattern struct { - value interface{} - op patternOp - subs []*pattern -} - -func (pat pattern) String() string { - if len(pat.subs) == 0 { - return fmt.Sprintf("<%s %#v>", pat.op, pat.value) - } - parts := make([]string, len(pat.subs)) - for i, sub := range pat.subs { - parts[i] = sub.String() - } - return fmt.Sprintf("<%s %#v (%s)>", pat.op, pat.value, strings.Join(parts, ", ")) -} - -type ImportsTab struct { - imports []map[string]string -} - -func NewImportsTab(initial map[string]string) *ImportsTab { - return &ImportsTab{imports: []map[string]string{initial}} -} - -func (itab *ImportsTab) Lookup(pkgName string) (string, bool) { - for i := len(itab.imports) - 1; i >= 0; i-- { - pkgPath, ok := itab.imports[i][pkgName] - if ok { - return pkgPath, true - } - } - return "", false -} - -func (itab *ImportsTab) Load(pkgName, pkgPath string) { - itab.imports[len(itab.imports)-1][pkgName] = pkgPath -} - -func (itab *ImportsTab) EnterScope() { - itab.imports = append(itab.imports, map[string]string{}) -} - -func (itab *ImportsTab) LeaveScope() { - itab.imports = itab.imports[:len(itab.imports)-1] -} - -type Context struct { - Itab *ImportsTab -} - -const ( - varPrefix = `ᐸvarᐳ` - varSeqPrefix = `ᐸvar_seqᐳ` -) - -func Parse(ctx *Context, s string) (*Pattern, error) { - noDollars := strings.ReplaceAll(s, "$*", varSeqPrefix) - noDollars = strings.ReplaceAll(noDollars, "$", varPrefix) - n, err := parser.ParseExpr(noDollars) - if err != nil { - return nil, err - } - root := parseExpr(ctx, n) - if root == nil { - return nil, fmt.Errorf("can't convert %s type expression", s) - } - p := &Pattern{ - root: root, - } - return p, nil -} - -var ( - builtinTypeByName = map[string]types.Type{ - "bool": types.Typ[types.Bool], - "int": types.Typ[types.Int], - "int8": types.Typ[types.Int8], - "int16": types.Typ[types.Int16], - "int32": types.Typ[types.Int32], - "int64": types.Typ[types.Int64], - "uint": types.Typ[types.Uint], - "uint8": types.Typ[types.Uint8], - "uint16": types.Typ[types.Uint16], - "uint32": types.Typ[types.Uint32], - "uint64": types.Typ[types.Uint64], - "uintptr": types.Typ[types.Uintptr], - "float32": types.Typ[types.Float32], - "float64": types.Typ[types.Float64], - "complex64": types.Typ[types.Complex64], - "complex128": types.Typ[types.Complex128], - "string": types.Typ[types.String], - - "error": types.Universe.Lookup("error").Type(), - - // Aliases. - "byte": types.Typ[types.Uint8], - "rune": types.Typ[types.Int32], - } - - efaceType = types.NewInterfaceType(nil, nil) -) - -func parseExpr(ctx *Context, e ast.Expr) *pattern { - switch e := e.(type) { - case *ast.Ident: - basic, ok := builtinTypeByName[e.Name] - if ok { - return &pattern{op: opBuiltinType, value: basic} - } - if strings.HasPrefix(e.Name, varPrefix) { - name := strings.TrimPrefix(e.Name, varPrefix) - return &pattern{op: opVar, value: name} - } - if strings.HasPrefix(e.Name, varSeqPrefix) { - name := strings.TrimPrefix(e.Name, varSeqPrefix) - // Only unnamed seq are supported right now. - if name == "_" { - return &pattern{op: opVarSeq, value: name} - } - } - - case *ast.SelectorExpr: - pkg, ok := e.X.(*ast.Ident) - if !ok { - return nil - } - if pkg.Name == "unsafe" && e.Sel.Name == "Pointer" { - return &pattern{op: opBuiltinType, value: types.Typ[types.UnsafePointer]} - } - pkgPath, ok := ctx.Itab.Lookup(pkg.Name) - if !ok { - return nil - } - return &pattern{op: opNamed, value: [2]string{pkgPath, e.Sel.Name}} - - case *ast.StarExpr: - elem := parseExpr(ctx, e.X) - if elem == nil { - return nil - } - return &pattern{op: opPointer, subs: []*pattern{elem}} - - case *ast.ArrayType: - elem := parseExpr(ctx, e.Elt) - if elem == nil { - return nil - } - if e.Len == nil { - return &pattern{ - op: opSlice, - subs: []*pattern{elem}, - } - } - if id, ok := e.Len.(*ast.Ident); ok && strings.HasPrefix(id.Name, varPrefix) { - name := strings.TrimPrefix(id.Name, varPrefix) - return &pattern{ - op: opArray, - value: name, - subs: []*pattern{elem}, - } - } - lit, ok := e.Len.(*ast.BasicLit) - if !ok || lit.Kind != token.INT { - return nil - } - length, err := strconv.ParseInt(lit.Value, 10, 64) - if err != nil { - return nil - } - return &pattern{ - op: opArray, - value: length, - subs: []*pattern{elem}, - } - - case *ast.MapType: - keyType := parseExpr(ctx, e.Key) - if keyType == nil { - return nil - } - valType := parseExpr(ctx, e.Value) - if valType == nil { - return nil - } - return &pattern{ - op: opMap, - subs: []*pattern{keyType, valType}, - } - - case *ast.ChanType: - valType := parseExpr(ctx, e.Value) - if valType == nil { - return nil - } - var dir types.ChanDir - switch { - case e.Dir&ast.SEND != 0 && e.Dir&ast.RECV != 0: - dir = types.SendRecv - case e.Dir&ast.SEND != 0: - dir = types.SendOnly - case e.Dir&ast.RECV != 0: - dir = types.RecvOnly - default: - return nil - } - return &pattern{ - op: opChan, - value: dir, - subs: []*pattern{valType}, - } - - case *ast.ParenExpr: - return parseExpr(ctx, e.X) - - case *ast.FuncType: - hasSeq := false - var params []*pattern - var results []*pattern - if e.Params != nil { - for _, field := range e.Params.List { - p := parseExpr(ctx, field.Type) - if p == nil { - return nil - } - if len(field.Names) != 0 { - return nil - } - if p.op == opVarSeq { - hasSeq = true - } - params = append(params, p) - } - } - if e.Results != nil { - for _, field := range e.Results.List { - p := parseExpr(ctx, field.Type) - if p == nil { - return nil - } - if len(field.Names) != 0 { - return nil - } - if p.op == opVarSeq { - hasSeq = true - } - results = append(results, p) - } - } - op := opFuncNoSeq - if hasSeq { - op = opFunc - } - return &pattern{ - op: op, - value: len(params), - subs: append(params, results...), - } - - case *ast.StructType: - hasSeq := false - members := make([]*pattern, 0, len(e.Fields.List)) - for _, field := range e.Fields.List { - p := parseExpr(ctx, field.Type) - if p == nil { - return nil - } - if len(field.Names) != 0 { - return nil - } - if p.op == opVarSeq { - hasSeq = true - } - members = append(members, p) - } - op := opStructNoSeq - if hasSeq { - op = opStruct - } - return &pattern{ - op: op, - subs: members, - } - - case *ast.InterfaceType: - if len(e.Methods.List) == 0 { - return &pattern{op: opBuiltinType, value: efaceType} - } - if len(e.Methods.List) == 1 { - p := parseExpr(ctx, e.Methods.List[0].Type) - if p == nil { - return nil - } - if p.op != opVarSeq { - return nil - } - return &pattern{op: opAnyInterface} - } - } - - return nil -} - -// MatchIdentical returns true if the go typ matches pattern p. -func (p *Pattern) MatchIdentical(state *MatcherState, typ types.Type) bool { - state.reset() - return p.matchIdentical(state, p.root, typ) -} - -func (p *Pattern) matchIdenticalFielder(state *MatcherState, subs []*pattern, f fielder) bool { - // TODO: do backtracking. - - numFields := f.NumFields() - fieldsMatched := 0 - - if len(subs) == 0 && numFields != 0 { - return false - } - - matchAny := false - - i := 0 - for i < len(subs) { - pat := subs[i] - - if pat.op == opVarSeq { - matchAny = true - } - - fieldsLeft := numFields - fieldsMatched - if matchAny { - switch { - // "Nothing left to match" stop condition. - case fieldsLeft == 0: - matchAny = false - i++ - // Lookahead for non-greedy matching. - case i+1 < len(subs) && p.matchIdentical(state, subs[i+1], f.Field(fieldsMatched).Type()): - matchAny = false - i += 2 - fieldsMatched++ - default: - fieldsMatched++ - } - continue - } - - if fieldsLeft == 0 || !p.matchIdentical(state, pat, f.Field(fieldsMatched).Type()) { - return false - } - i++ - fieldsMatched++ - } - - return numFields == fieldsMatched -} - -func (p *Pattern) matchIdentical(state *MatcherState, sub *pattern, typ types.Type) bool { - switch sub.op { - case opVar: - name := sub.value.(string) - if name == "_" { - return true - } - y, ok := state.typeMatches[name] - if !ok { - state.typeMatches[name] = typ - return true - } - if y == nil { - return typ == nil - } - return xtypes.Identical(typ, y) - - case opBuiltinType: - return xtypes.Identical(typ, sub.value.(types.Type)) - - case opPointer: - typ, ok := typ.(*types.Pointer) - if !ok { - return false - } - return p.matchIdentical(state, sub.subs[0], typ.Elem()) - - case opSlice: - typ, ok := typ.(*types.Slice) - if !ok { - return false - } - return p.matchIdentical(state, sub.subs[0], typ.Elem()) - - case opArray: - typ, ok := typ.(*types.Array) - if !ok { - return false - } - var wantLen int64 - switch v := sub.value.(type) { - case string: - if v == "_" { - wantLen = typ.Len() - break - } - length, ok := state.int64Matches[v] - if ok { - wantLen = length - } else { - state.int64Matches[v] = typ.Len() - wantLen = typ.Len() - } - case int64: - wantLen = v - } - return wantLen == typ.Len() && p.matchIdentical(state, sub.subs[0], typ.Elem()) - - case opMap: - typ, ok := typ.(*types.Map) - if !ok { - return false - } - return p.matchIdentical(state, sub.subs[0], typ.Key()) && - p.matchIdentical(state, sub.subs[1], typ.Elem()) - - case opChan: - typ, ok := typ.(*types.Chan) - if !ok { - return false - } - dir := sub.value.(types.ChanDir) - return dir == typ.Dir() && p.matchIdentical(state, sub.subs[0], typ.Elem()) - - case opNamed: - typ, ok := typ.(*types.Named) - if !ok { - return false - } - obj := typ.Obj() - pkg := obj.Pkg() - // pkg can be nil for builtin named types. - // There is no point in checking anything else as we never - // generate the opNamed for such types. - if pkg == nil { - return false - } - pkgPath := sub.value.([2]string)[0] - typeName := sub.value.([2]string)[1] - if typeName != obj.Name() { - return false - } - objPath := obj.Pkg().Path() - if vendorPos := strings.Index(objPath, "/vendor/"); vendorPos != -1 { - objPath = objPath[vendorPos+len("/vendor/"):] - } - return objPath == pkgPath - - case opFuncNoSeq: - typ, ok := typ.(*types.Signature) - if !ok { - return false - } - numParams := sub.value.(int) - params := sub.subs[:numParams] - results := sub.subs[numParams:] - if typ.Params().Len() != len(params) { - return false - } - if typ.Results().Len() != len(results) { - return false - } - for i := 0; i < typ.Params().Len(); i++ { - if !p.matchIdentical(state, params[i], typ.Params().At(i).Type()) { - return false - } - } - for i := 0; i < typ.Results().Len(); i++ { - if !p.matchIdentical(state, results[i], typ.Results().At(i).Type()) { - return false - } - } - return true - - case opFunc: - typ, ok := typ.(*types.Signature) - if !ok { - return false - } - numParams := sub.value.(int) - params := sub.subs[:numParams] - results := sub.subs[numParams:] - adapter := tupleFielder{x: typ.Params()} - if !p.matchIdenticalFielder(state, params, &adapter) { - return false - } - adapter.x = typ.Results() - if !p.matchIdenticalFielder(state, results, &adapter) { - return false - } - return true - - case opStructNoSeq: - typ, ok := typ.(*types.Struct) - if !ok { - return false - } - if typ.NumFields() != len(sub.subs) { - return false - } - for i, member := range sub.subs { - if !p.matchIdentical(state, member, typ.Field(i).Type()) { - return false - } - } - return true - - case opStruct: - typ, ok := typ.(*types.Struct) - if !ok { - return false - } - if !p.matchIdenticalFielder(state, sub.subs, typ) { - return false - } - return true - - case opAnyInterface: - _, ok := typ.(*types.Interface) - return ok - - default: - return false - } -} - -type fielder interface { - Field(i int) *types.Var - NumFields() int -} - -type tupleFielder struct { - x *types.Tuple -} - -func (tup *tupleFielder) Field(i int) *types.Var { return tup.x.At(i) } -func (tup *tupleFielder) NumFields() int { return tup.x.Len() } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go deleted file mode 100644 index 6403d91cd..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go +++ /dev/null @@ -1,304 +0,0 @@ -package ruleguard - -import ( - "go/ast" - "go/constant" - "go/parser" - "go/token" - "go/types" - "regexp/syntax" - "strconv" - "strings" - - "golang.org/x/exp/typeparams" -) - -var invalidType = types.Typ[types.Invalid] - -func regexpHasCaptureGroups(pattern string) bool { - // regexp.Compile() uses syntax.Perl flags, so - // we use the same flags here. - re, err := syntax.Parse(pattern, syntax.Perl) - if err != nil { - return true // true is more conservative than false - } - - found := false - - var walkRegexp func(*syntax.Regexp) - walkRegexp = func(re *syntax.Regexp) { - if found { - return - } - // OpCapture handles both named and unnamed capture groups. - if re.Op == syntax.OpCapture { - found = true - return - } - for _, sub := range re.Sub { - walkRegexp(sub) - } - } - walkRegexp(re) - - return found -} - -func findDependency(pkg *types.Package, path string) *types.Package { - if pkg.Path() == path { - return pkg - } - // It looks like indirect dependencies are always incomplete? - // If it's true, then we don't have to recurse here. - for _, imported := range pkg.Imports() { - if dep := findDependency(imported, path); dep != nil && dep.Complete() { - return dep - } - } - return nil -} - -var typeByName = map[string]types.Type{ - // Predeclared types. - `error`: types.Universe.Lookup("error").Type(), - `bool`: types.Typ[types.Bool], - `int`: types.Typ[types.Int], - `int8`: types.Typ[types.Int8], - `int16`: types.Typ[types.Int16], - `int32`: types.Typ[types.Int32], - `int64`: types.Typ[types.Int64], - `uint`: types.Typ[types.Uint], - `uint8`: types.Typ[types.Uint8], - `uint16`: types.Typ[types.Uint16], - `uint32`: types.Typ[types.Uint32], - `uint64`: types.Typ[types.Uint64], - `uintptr`: types.Typ[types.Uintptr], - `string`: types.Typ[types.String], - `float32`: types.Typ[types.Float32], - `float64`: types.Typ[types.Float64], - `complex64`: types.Typ[types.Complex64], - `complex128`: types.Typ[types.Complex128], - - // Predeclared aliases (provided for convenience). - `byte`: types.Typ[types.Uint8], - `rune`: types.Typ[types.Int32], -} - -func typeFromString(s string) (types.Type, error) { - s = strings.ReplaceAll(s, "?", "__any") - - n, err := parser.ParseExpr(s) - if err != nil { - return nil, err - } - return typeFromNode(n), nil -} - -func typeFromNode(e ast.Expr) types.Type { - switch e := e.(type) { - case *ast.Ident: - typ, ok := typeByName[e.Name] - if ok { - return typ - } - - case *ast.ArrayType: - elem := typeFromNode(e.Elt) - if elem == nil { - return nil - } - if e.Len == nil { - return types.NewSlice(elem) - } - lit, ok := e.Len.(*ast.BasicLit) - if !ok || lit.Kind != token.INT { - return nil - } - length, err := strconv.Atoi(lit.Value) - if err != nil { - return nil - } - return types.NewArray(elem, int64(length)) - - case *ast.MapType: - keyType := typeFromNode(e.Key) - if keyType == nil { - return nil - } - valType := typeFromNode(e.Value) - if valType == nil { - return nil - } - return types.NewMap(keyType, valType) - - case *ast.StarExpr: - typ := typeFromNode(e.X) - if typ != nil { - return types.NewPointer(typ) - } - - case *ast.ParenExpr: - return typeFromNode(e.X) - - case *ast.InterfaceType: - if len(e.Methods.List) == 0 { - return types.NewInterfaceType(nil, nil) - } - } - - return nil -} - -func intValueOf(info *types.Info, expr ast.Expr) constant.Value { - tv := info.Types[expr] - if tv.Value == nil { - return nil - } - if tv.Value.Kind() != constant.Int { - return nil - } - return tv.Value -} - -// isPure reports whether expr is a softly safe expression and contains -// no significant side-effects. As opposed to strictly safe expressions, -// soft safe expressions permit some forms of side-effects, like -// panic possibility during indexing or nil pointer dereference. -// -// Uses types info to determine type conversion expressions that -// are the only permitted kinds of call expressions. -// Note that is does not check whether called function really -// has any side effects. The analysis is very conservative. -func isPure(info *types.Info, expr ast.Expr) bool { - // This list switch is not comprehensive and uses - // whitelist to be on the conservative side. - // Can be extended as needed. - - switch expr := expr.(type) { - case *ast.StarExpr: - return isPure(info, expr.X) - case *ast.BinaryExpr: - return isPure(info, expr.X) && - isPure(info, expr.Y) - case *ast.UnaryExpr: - return expr.Op != token.ARROW && - isPure(info, expr.X) - case *ast.BasicLit, *ast.Ident, *ast.FuncLit: - return true - case *ast.IndexExpr: - return isPure(info, expr.X) && - isPure(info, expr.Index) - case *ast.SelectorExpr: - return isPure(info, expr.X) - case *ast.ParenExpr: - return isPure(info, expr.X) - case *ast.CompositeLit: - return isPureList(info, expr.Elts) - case *ast.CallExpr: - return isTypeExpr(info, expr.Fun) && isPureList(info, expr.Args) - - default: - return false - } -} - -// isPureList reports whether every expr in list is safe. -// -// See isPure. -func isPureList(info *types.Info, list []ast.Expr) bool { - for _, expr := range list { - if !isPure(info, expr) { - return false - } - } - return true -} - -func isAddressable(info *types.Info, expr ast.Expr) bool { - tv, ok := info.Types[expr] - return ok && tv.Addressable() -} - -func isConstant(info *types.Info, expr ast.Expr) bool { - tv, ok := info.Types[expr] - return ok && tv.Value != nil -} - -func isConstantSlice(info *types.Info, expr ast.Expr) bool { - switch expr := expr.(type) { - case *ast.CallExpr: - // Matches []byte("string"). - if len(expr.Args) != 1 { - return false - } - lit, ok := expr.Args[0].(*ast.BasicLit) - if !ok || lit.Kind != token.STRING { - return false - } - typ, ok := info.TypeOf(expr.Fun).(*types.Slice) - if !ok { - return false - } - basicType, ok := typ.Elem().(*types.Basic) - return ok && basicType.Kind() == types.Uint8 - - case *ast.CompositeLit: - for _, elt := range expr.Elts { - if !isConstant(info, elt) { - return false - } - } - return true - - default: - return false - } -} - -// isTypeExpr reports whether x represents a type expression. -// -// Type expression does not evaluate to any run time value, -// but rather describes a type that is used inside Go expression. -// -// For example, (*T)(v) is a CallExpr that "calls" (*T). -// (*T) is a type expression that tells Go compiler type v should be converted to. -func isTypeExpr(info *types.Info, x ast.Expr) bool { - switch x := x.(type) { - case *ast.StarExpr: - return isTypeExpr(info, x.X) - case *ast.ParenExpr: - return isTypeExpr(info, x.X) - case *ast.SelectorExpr: - return isTypeExpr(info, x.Sel) - - case *ast.Ident: - // Identifier may be a type expression if object - // it refers to is a type name. - _, ok := info.ObjectOf(x).(*types.TypeName) - return ok - - case *ast.FuncType, *ast.StructType, *ast.InterfaceType, *ast.ArrayType, *ast.MapType, *ast.ChanType: - return true - - default: - return false - } -} - -func identOf(e ast.Expr) *ast.Ident { - switch e := e.(type) { - case *ast.ParenExpr: - return identOf(e.X) - case *ast.Ident: - return e - case *ast.SelectorExpr: - return e.Sel - default: - return nil - } -} - -func isTypeParam(typ types.Type) bool { - _, ok := typ.(*typeparams.TypeParam) - return ok -} diff --git a/vendor/github.com/quasilyte/gogrep/.gitignore b/vendor/github.com/quasilyte/gogrep/.gitignore deleted file mode 100644 index ec560f1c9..000000000 --- a/vendor/github.com/quasilyte/gogrep/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.idea -.vscode -coverage.txt -bin diff --git a/vendor/github.com/quasilyte/gogrep/.golangci.yml b/vendor/github.com/quasilyte/gogrep/.golangci.yml deleted file mode 100644 index 16d03c54d..000000000 --- a/vendor/github.com/quasilyte/gogrep/.golangci.yml +++ /dev/null @@ -1,49 +0,0 @@ -{ - "run": { - # timeout for analysis, e.g. 30s, 5m, default is 1m - "deadline": "3m", - }, - "fast": false, - "linters": { - "enable": [ - "deadcode", - "errcheck", - "gas", - "gocritic", - "gofmt", - "goimports", - "revive", - "govet", - "gosimple", - "ineffassign", - "megacheck", - "misspell", - "nakedret", - "staticcheck", - "structcheck", - "typecheck", - "unconvert", - "unused", - "varcheck", - ], - }, - "disable": [ - "depguard", - "dupl", - "gocyclo", - "interfacer", - "lll", - "maligned", - "prealloc", - ], - "linters-settings": { - "gocritic": { - "enabled-tags": [ - "style", - "diagnostic", - "performance", - "experimental", - ], - }, - }, -} diff --git a/vendor/github.com/quasilyte/gogrep/LICENSE b/vendor/github.com/quasilyte/gogrep/LICENSE deleted file mode 100644 index 575b56ae1..000000000 --- a/vendor/github.com/quasilyte/gogrep/LICENSE +++ /dev/null @@ -1,33 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2021, Iskander (Alex) Sharipov - -Originally based on the Daniel Martí code | Copyright (c) 2017, Daniel Martí. All rights reserved. -See https://github.com/mvdan/gogrep - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/quasilyte/gogrep/Makefile b/vendor/github.com/quasilyte/gogrep/Makefile deleted file mode 100644 index 01dd2192e..000000000 --- a/vendor/github.com/quasilyte/gogrep/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -GOPATH_DIR=`go env GOPATH` - -test: - go test -count 2 -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic ./... - go test -bench=. ./... - @echo "everything is OK" - -ci-lint: - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH_DIR)/bin v1.45.2 - $(GOPATH_DIR)/bin/golangci-lint run ./... - go install github.com/quasilyte/go-consistent@master - $(GOPATH_DIR)/bin/go-consistent . ./internal/... ./nodetag/... ./filters/... - @echo "everything is OK" - -lint: - golangci-lint run ./... - @echo "everything is OK" - -.PHONY: ci-lint lint test diff --git a/vendor/github.com/quasilyte/gogrep/README.md b/vendor/github.com/quasilyte/gogrep/README.md deleted file mode 100644 index ecf0dc4c7..000000000 --- a/vendor/github.com/quasilyte/gogrep/README.md +++ /dev/null @@ -1,41 +0,0 @@ -![logo](https://github.com/quasilyte/vscode-gogrep/blob/master/docs/logo.png?raw=true) - -![Build Status](https://github.com/quasilyte/gogrep/workflows/Go/badge.svg) -[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/quasilyte/gogrep)](https://pkg.go.dev/github.com/quasilyte/gogrep) -[![Go Report Card](https://goreportcard.com/badge/github.com/quasilyte/gogrep)](https://goreportcard.com/report/github.com/quasilyte/gogrep) -![Code Coverage](https://codecov.io/gh/quasilyte/gogrep/branch/master/graph/badge.svg) - -# gogrep - -This is an attempt to move a modified [gogrep](https://github.com/mvdan/gogrep) from the [go-ruleguard](https://github.com/quasilyte/go-ruleguard) project, so it can be used independently. - -This repository contains two Go modules. One for the gogrep library and the second one for the command-line tool. - -## gogrep as a library - -To get a gogrep library module, install the root Go module. - -```bash -$ go get github.com/quasilyte/gogrep -``` - -## gogrep as a command-line utility - -To get a gogrep command-line tool, install the `cmd/gogrep` Go submodule. - -```bash -$ go install github.com/quasilyte/gogrep/cmd/gogrep@latest -``` - -See [docs/gogrep_cli.md](_docs/gogrep_cli.md) to learn how to use it. - -## Used by - -A gogrep library is used by: - -* [go-ruleguard](https://github.com/quasilyte/go-ruleguard) -* [gocorpus](https://github.com/quasilyte/gocorpus) - -## Acknowledgements - -The original gogrep is written by the [Daniel Martí](https://github.com/mvdan). diff --git a/vendor/github.com/quasilyte/gogrep/compile.go b/vendor/github.com/quasilyte/gogrep/compile.go deleted file mode 100644 index 31b60dfa5..000000000 --- a/vendor/github.com/quasilyte/gogrep/compile.go +++ /dev/null @@ -1,1264 +0,0 @@ -package gogrep - -import ( - "fmt" - "go/ast" - "go/token" - - "github.com/quasilyte/gogrep/internal/stdinfo" - "golang.org/x/exp/typeparams" -) - -type compileError string - -func (e compileError) Error() string { return string(e) } - -type compiler struct { - config CompileConfig - - prog *program - stringIndexes map[string]uint8 - ifaceIndexes map[interface{}]uint8 - - info *PatternInfo - - insideStmtList bool -} - -func (c *compiler) Compile(root ast.Node, info *PatternInfo) (p *program, err error) { - defer func() { - if err != nil { - return - } - rv := recover() - if rv == nil { - return - } - if parseErr, ok := rv.(compileError); ok { - err = parseErr - return - } - panic(rv) // Not our panic - }() - - c.info = info - c.prog = &program{ - insts: make([]instruction, 0, 8), - } - c.stringIndexes = make(map[string]uint8) - c.ifaceIndexes = make(map[interface{}]uint8) - - c.compileNode(root) - - if len(c.prog.insts) == 0 { - return nil, c.errorf(root, "0 instructions generated") - } - - return c.prog, nil -} - -func (c *compiler) errorf(n ast.Node, format string, args ...interface{}) compileError { - loc := c.config.Fset.Position(n.Pos()) - message := fmt.Sprintf("%s:%d: %s", loc.Filename, loc.Line, fmt.Sprintf(format, args...)) - return compileError(message) -} - -func (c *compiler) toUint8(n ast.Node, v int) uint8 { - if !fitsUint8(v) { - panic(c.errorf(n, "implementation error: %v can't be converted to uint8", v)) - } - return uint8(v) -} - -func (c *compiler) internVar(n ast.Node, s string) uint8 { - c.info.Vars[s] = struct{}{} - index := c.internString(n, s) - return index -} - -func (c *compiler) internString(n ast.Node, s string) uint8 { - if index, ok := c.stringIndexes[s]; ok { - return index - } - index := len(c.prog.strings) - if !fitsUint8(index) { - panic(c.errorf(n, "implementation limitation: too many string values")) - } - c.stringIndexes[s] = uint8(index) - c.prog.strings = append(c.prog.strings, s) - return uint8(index) -} - -func (c *compiler) internIface(n ast.Node, v interface{}) uint8 { - if index, ok := c.ifaceIndexes[v]; ok { - return index - } - index := len(c.prog.ifaces) - if !fitsUint8(index) { - panic(c.errorf(n, "implementation limitation: too many values")) - } - c.ifaceIndexes[v] = uint8(index) - c.prog.ifaces = append(c.prog.ifaces, v) - return uint8(index) -} - -func (c *compiler) emitInst(inst instruction) { - c.prog.insts = append(c.prog.insts, inst) -} - -func (c *compiler) emitInstOp(op operation) { - c.emitInst(instruction{op: op}) -} - -func (c *compiler) compileNode(n ast.Node) { - switch n := n.(type) { - case *ast.File: - c.compileFile(n) - case ast.Decl: - c.compileDecl(n) - case ast.Expr: - c.compileExpr(n) - case ast.Stmt: - c.compileStmt(n) - case *ast.ValueSpec: - c.compileValueSpec(n) - case *rangeClause: - c.compileRangeClause(n) - case *rangeHeader: - c.compileRangeHeader(n) - case *NodeSlice: - switch n.Kind { - case StmtNodeSlice: - c.compileStmtSlice(n.stmtSlice) - case DeclNodeSlice: - c.compileDeclSlice(n.declSlice) - case ExprNodeSlice: - c.compileExprSlice(n.exprSlice) - } - default: - panic(c.errorf(n, "compileNode: unexpected %T", n)) - } -} - -func (c *compiler) compileOptStmt(n ast.Stmt) { - if exprStmt, ok := n.(*ast.ExprStmt); ok { - if ident, ok := exprStmt.X.(*ast.Ident); ok && isWildName(ident.Name) { - c.compileWildIdent(ident, true) - return - } - } - c.compileStmt(n) -} - -func (c *compiler) compileOptExpr(n ast.Expr) { - if ident, ok := n.(*ast.Ident); ok && isWildName(ident.Name) { - c.compileWildIdent(ident, true) - return - } - c.compileExpr(n) -} - -func (c *compiler) compileOptFieldList(n *ast.FieldList) { - if len(n.List) == 1 { - if ident, ok := n.List[0].Type.(*ast.Ident); ok && isWildName(ident.Name) && len(n.List[0].Names) == 0 { - // `func (...) $*result` - result could be anything - // `func (...) $result` - result is a field list of 1 element - info := decodeWildName(ident.Name) - switch { - case info.Seq: - c.compileWildIdent(ident, true) - case info.Name == "_": - c.emitInstOp(opFieldNode) - default: - c.emitInst(instruction{ - op: opNamedFieldNode, - valueIndex: c.internVar(n, info.Name), - }) - } - return - } - } - c.compileFieldList(n) -} - -func (c *compiler) compileFieldList(n *ast.FieldList) { - c.emitInstOp(opFieldList) - for _, x := range n.List { - c.compileField(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileField(n *ast.Field) { - switch { - case len(n.Names) == 0: - if ident, ok := n.Type.(*ast.Ident); ok && isWildName(ident.Name) { - c.compileWildIdent(ident, false) - return - } - c.emitInstOp(opUnnamedField) - case len(n.Names) == 1: - name := n.Names[0] - if isWildName(name.Name) { - c.emitInstOp(opField) - c.compileWildIdent(name, false) - } else { - c.emitInst(instruction{ - op: opSimpleField, - valueIndex: c.internString(name, name.Name), - }) - } - default: - c.emitInstOp(opMultiField) - for _, name := range n.Names { - c.compileIdent(name) - } - c.emitInstOp(opEnd) - } - c.compileTypeExpr(n.Type) -} - -func (c *compiler) compileValueSpec(spec *ast.ValueSpec) { - switch { - case spec.Type == nil && len(spec.Values) == 0: - if isWildName(spec.Names[0].String()) { - c.compileIdent(spec.Names[0]) - return - } - c.emitInstOp(opValueSpec) - case spec.Type == nil: - c.emitInstOp(opValueInitSpec) - case len(spec.Values) == 0: - c.emitInstOp(opTypedValueSpec) - default: - c.emitInstOp(opTypedValueInitSpec) - } - for _, name := range spec.Names { - c.compileIdent(name) - } - c.emitInstOp(opEnd) - if spec.Type != nil { - c.compileOptTypeExpr(spec.Type) - } - if len(spec.Values) != 0 { - for _, v := range spec.Values { - c.compileExpr(v) - } - c.emitInstOp(opEnd) - } -} - -func (c *compiler) compileTypeSpec(spec *ast.TypeSpec) { - // Generic types can't have aliases, so we use that fact here. - typeParams := typeparams.ForTypeSpec(spec) - if !spec.Assign.IsValid() && !isWildName(spec.Name.Name) && typeParams == nil { - c.emitInst(instruction{ - op: opSimpleTypeSpec, - valueIndex: c.internString(spec.Name, spec.Name.Name), - }) - c.compileTypeExpr(spec.Type) - return - } - if typeParams != nil { - c.emitInstOp(opGenericTypeSpec) - c.compileIdent(spec.Name) - c.compileFieldList(typeParams) - c.compileTypeExpr(spec.Type) - return - } - c.emitInstOp(pickOp(spec.Assign.IsValid(), opTypeAliasSpec, opTypeSpec)) - c.compileIdent(spec.Name) - c.compileTypeExpr(spec.Type) -} - -func (c *compiler) compileFile(n *ast.File) { - if len(n.Imports) == 0 && len(n.Decls) == 0 { - c.emitInstOp(opEmptyPackage) - c.compileIdent(n.Name) - return - } - - panic(c.errorf(n, "compileFile: unsupported file pattern")) -} - -func (c *compiler) compileDecl(n ast.Decl) { - switch n := n.(type) { - case *ast.FuncDecl: - c.compileFuncDecl(n) - case *ast.GenDecl: - c.compileGenDecl(n) - - default: - panic(c.errorf(n, "compileDecl: unexpected %T", n)) - } -} - -func (c *compiler) compileFuncDecl(n *ast.FuncDecl) { - if n.Recv == nil { - if !isWildName(n.Name.Name) && typeparams.ForFuncType(n.Type) == nil && n.Body != nil { - // Generic functions can't live without body, so there is no generic proto decls. - c.emitInst(instruction{ - op: opSimpleFuncDecl, - valueIndex: c.internString(n.Name, n.Name.Name), - }) - c.compileFuncType(n.Type) - c.compileBlockStmt(n.Body) - return - } - c.emitInstOp(pickOp(n.Body == nil, opFuncProtoDecl, opFuncDecl)) - } else { - c.emitInstOp(pickOp(n.Body == nil, opMethodProtoDecl, opMethodDecl)) - } - - if n.Recv != nil { - c.compileFieldList(n.Recv) - } - c.compileIdent(n.Name) - c.compileFuncType(n.Type) - if n.Body != nil { - c.compileBlockStmt(n.Body) - } -} - -func (c *compiler) compileGenDecl(n *ast.GenDecl) { - if c.insideStmtList { - c.emitInstOp(opDeclStmt) - } - - switch n.Tok { - case token.CONST, token.VAR: - c.emitInstOp(pickOp(n.Tok == token.CONST, opConstDecl, opVarDecl)) - for _, spec := range n.Specs { - c.compileValueSpec(spec.(*ast.ValueSpec)) - } - c.emitInstOp(opEnd) - case token.TYPE: - c.emitInstOp(opTypeDecl) - for _, spec := range n.Specs { - c.compileTypeSpec(spec.(*ast.TypeSpec)) - } - c.emitInstOp(opEnd) - - default: - panic(c.errorf(n, "unexpected gen decl")) - } -} - -func (c *compiler) compileTypeExpr(n ast.Expr) { - if ident, ok := n.(*ast.Ident); ok && ident.Name == "any" && !c.config.Strict && typeparams.Enabled() { - c.emitInstOp(opEfaceType) - return - } - c.compileExpr(n) -} - -func (c *compiler) compileOptTypeExpr(n ast.Expr) { - if ident, ok := n.(*ast.Ident); ok && isWildName(ident.Name) { - c.compileWildIdent(ident, true) - return - } - c.compileTypeExpr(n) -} - -func (c *compiler) compileExpr(n ast.Expr) { - switch n := n.(type) { - case *ast.BasicLit: - c.compileBasicLit(n) - case *ast.BinaryExpr: - c.compileBinaryExpr(n) - case *ast.IndexExpr: - c.compileIndexExpr(n) - case *typeparams.IndexListExpr: - c.compileIndexListExpr(n) - case *ast.Ident: - c.compileIdent(n) - case *ast.CallExpr: - c.compileCallExpr(n) - case *ast.UnaryExpr: - c.compileUnaryExpr(n) - case *ast.StarExpr: - c.compileStarExpr(n) - case *ast.ParenExpr: - c.compileParenExpr(n) - case *ast.SliceExpr: - c.compileSliceExpr(n) - case *ast.StructType: - c.compileStructType(n) - case *ast.InterfaceType: - c.compileInterfaceType(n) - case *ast.FuncType: - c.compileFuncType(n) - case *ast.ArrayType: - c.compileArrayType(n) - case *ast.MapType: - c.compileMapType(n) - case *ast.ChanType: - c.compileChanType(n) - case *ast.CompositeLit: - c.compileCompositeLit(n) - case *ast.FuncLit: - c.compileFuncLit(n) - case *ast.Ellipsis: - c.compileEllipsis(n) - case *ast.KeyValueExpr: - c.compileKeyValueExpr(n) - case *ast.SelectorExpr: - c.compileSelectorExpr(n) - case *ast.TypeAssertExpr: - c.compileTypeAssertExpr(n) - - default: - panic(c.errorf(n, "compileExpr: unexpected %T", n)) - } -} - -func (c *compiler) compileBasicLit(n *ast.BasicLit) { - if !c.config.Strict { - v := literalValue(n) - if v == nil { - panic(c.errorf(n, "can't convert %s (%s) value", n.Value, n.Kind)) - } - c.prog.insts = append(c.prog.insts, instruction{ - op: opBasicLit, - valueIndex: c.internIface(n, v), - }) - return - } - - var inst instruction - switch n.Kind { - case token.INT: - inst.op = opStrictIntLit - case token.FLOAT: - inst.op = opStrictFloatLit - case token.STRING: - inst.op = opStrictStringLit - case token.CHAR: - inst.op = opStrictCharLit - default: - inst.op = opStrictComplexLit - } - inst.valueIndex = c.internString(n, n.Value) - c.prog.insts = append(c.prog.insts, inst) -} - -func (c *compiler) compileBinaryExpr(n *ast.BinaryExpr) { - c.prog.insts = append(c.prog.insts, instruction{ - op: opBinaryExpr, - value: c.toUint8(n, int(n.Op)), - }) - c.compileExpr(n.X) - c.compileExpr(n.Y) -} - -func (c *compiler) compileIndexExpr(n *ast.IndexExpr) { - c.emitInstOp(opIndexExpr) - c.compileExpr(n.X) - c.compileExpr(n.Index) -} - -func (c *compiler) compileIndexListExpr(n *typeparams.IndexListExpr) { - c.emitInstOp(opIndexListExpr) - c.compileExpr(n.X) - for _, x := range n.Indices { - c.compileExpr(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileWildIdent(n *ast.Ident, optional bool) { - info := decodeWildName(n.Name) - var inst instruction - switch { - case info.Name == "_" && !info.Seq: - inst.op = opNode - case info.Name == "_" && info.Seq: - inst.op = pickOp(optional, opOptNode, opNodeSeq) - case info.Name != "_" && !info.Seq: - inst.op = opNamedNode - inst.valueIndex = c.internVar(n, info.Name) - default: - inst.op = pickOp(optional, opNamedOptNode, opNamedNodeSeq) - inst.valueIndex = c.internVar(n, info.Name) - } - c.prog.insts = append(c.prog.insts, inst) -} - -func (c *compiler) compileIdent(n *ast.Ident) { - if isWildName(n.Name) { - c.compileWildIdent(n, false) - return - } - - c.prog.insts = append(c.prog.insts, instruction{ - op: opIdent, - valueIndex: c.internString(n, n.Name), - }) -} - -func (c *compiler) compileExprMembers(list []ast.Expr) { - isSimple := len(list) <= 255 - if isSimple { - for _, x := range list { - if decodeWildNode(x).Seq { - isSimple = false - break - } - } - } - - if isSimple { - c.emitInst(instruction{ - op: opSimpleArgList, - value: uint8(len(list)), - }) - for _, x := range list { - c.compileExpr(x) - } - } else { - c.emitInstOp(opArgList) - for _, x := range list { - c.compileExpr(x) - } - c.emitInstOp(opEnd) - } -} - -func (c *compiler) compileCallExpr(n *ast.CallExpr) { - variadicOperation := func(n *ast.CallExpr) (operation, uint8) { - if len(n.Args) == 0 { - return opNonVariadicCallExpr, 0 - } - lastArg, ok := n.Args[len(n.Args)-1].(*ast.Ident) - if !ok { - return opNonVariadicCallExpr, 0 - } - if !isWildName(lastArg.Name) || !decodeWildName(lastArg.Name).Seq { - return opNonVariadicCallExpr, 0 - } - if len(n.Args) == 1 { - return opCallExpr, 0 - } - // If there is any seq op before the lastArg, we emit opCallExpr too. - for i := 0; i < len(n.Args)-1; i++ { - if decodeWildNode(n.Args[i]).Seq { - return opCallExpr, 0 - } - } - return opMaybeVariadicCallExpr, c.toUint8(n, len(n.Args)-1) - } - - var value uint8 - var op operation - if n.Ellipsis.IsValid() { - op = opVariadicCallExpr - } else { - op, value = variadicOperation(n) - } - - c.prog.insts = append(c.prog.insts, instruction{ - op: op, - value: value, - }) - c.compileSymbol(n.Fun) - c.compileExprMembers(n.Args) -} - -// compileSymbol is mostly like a normal compileExpr, but it's used -// in places where we can find a type/function symbol. -// -// For example, in function call expressions a called function expression -// can look like `fmt.Sprint`. It will be compiled as a special -// selector expression that requires `fmt` to be a package as opposed -// to only check that it's an identifier with "fmt" value. -func (c *compiler) compileSymbol(sym ast.Expr) { - compilePkgSymbol := func(c *compiler, sym ast.Expr) bool { - e, ok := sym.(*ast.SelectorExpr) - if !ok { - return false - } - ident, ok := e.X.(*ast.Ident) - if !ok || isWildName(e.Sel.Name) { - return false - } - pkgPath := c.config.Imports[ident.Name] - if pkgPath == "" && stdinfo.Packages[ident.Name] != "" { - pkgPath = stdinfo.Packages[ident.Name] - } - if pkgPath == "" { - return false - } - c.emitInst(instruction{ - op: opSimpleSelectorExpr, - valueIndex: c.internString(e.Sel, e.Sel.String()), - }) - c.emitInst(instruction{ - op: opPkg, - valueIndex: c.internString(ident, pkgPath), - }) - return true - } - - if c.config.WithTypes { - if compilePkgSymbol(c, sym) { - return - } - } - - c.compileExpr(sym) -} - -func (c *compiler) compileUnaryExpr(n *ast.UnaryExpr) { - c.prog.insts = append(c.prog.insts, instruction{ - op: opUnaryExpr, - value: c.toUint8(n, int(n.Op)), - }) - c.compileExpr(n.X) -} - -func (c *compiler) compileStarExpr(n *ast.StarExpr) { - c.emitInstOp(opStarExpr) - c.compileExpr(n.X) -} - -func (c *compiler) compileParenExpr(n *ast.ParenExpr) { - c.emitInstOp(opParenExpr) - c.compileExpr(n.X) -} - -func (c *compiler) compileSliceExpr(n *ast.SliceExpr) { - switch { - case n.Low == nil && n.High == nil && !n.Slice3: - c.emitInstOp(opSliceExpr) - c.compileOptExpr(n.X) - case n.Low != nil && n.High == nil && !n.Slice3: - c.emitInstOp(opSliceFromExpr) - c.compileOptExpr(n.X) - c.compileOptExpr(n.Low) - case n.Low == nil && n.High != nil && !n.Slice3: - c.emitInstOp(opSliceToExpr) - c.compileOptExpr(n.X) - c.compileOptExpr(n.High) - case n.Low != nil && n.High != nil && !n.Slice3: - c.emitInstOp(opSliceFromToExpr) - c.compileOptExpr(n.X) - c.compileOptExpr(n.Low) - c.compileOptExpr(n.High) - case n.Low == nil && n.Slice3: - c.emitInstOp(opSliceToCapExpr) - c.compileOptExpr(n.X) - c.compileOptExpr(n.High) - c.compileOptExpr(n.Max) - case n.Low != nil && n.Slice3: - c.emitInstOp(opSliceFromToCapExpr) - c.compileOptExpr(n.X) - c.compileOptExpr(n.Low) - c.compileOptExpr(n.High) - c.compileOptExpr(n.Max) - default: - panic(c.errorf(n, "unexpected slice expr")) - } -} - -func (c *compiler) compileStructType(n *ast.StructType) { - c.emitInstOp(opStructType) - c.compileOptFieldList(n.Fields) -} - -func (c *compiler) compileInterfaceType(n *ast.InterfaceType) { - if len(n.Methods.List) == 0 && !c.config.Strict { - c.emitInstOp(opEfaceType) - return - } - c.emitInstOp(opInterfaceType) - c.compileOptFieldList(n.Methods) -} - -func (c *compiler) compileFuncType(n *ast.FuncType) { - void := n.Results == nil || len(n.Results.List) == 0 - typeParams := typeparams.ForFuncType(n) - if void { - if typeParams == nil { - c.emitInstOp(opVoidFuncType) - } else { - c.emitInstOp(opGenericVoidFuncType) - } - } else { - if typeParams == nil { - c.emitInstOp(opFuncType) - } else { - c.emitInstOp(opGenericFuncType) - } - } - if typeParams != nil { - c.compileOptFieldList(typeParams) - } - c.compileOptFieldList(n.Params) - if !void { - c.compileOptFieldList(n.Results) - } -} - -func (c *compiler) compileArrayType(n *ast.ArrayType) { - if n.Len == nil { - c.emitInstOp(opSliceType) - c.compileTypeExpr(n.Elt) - } else { - c.emitInstOp(opArrayType) - c.compileExpr(n.Len) - c.compileTypeExpr(n.Elt) - } -} - -func (c *compiler) compileMapType(n *ast.MapType) { - c.emitInstOp(opMapType) - c.compileTypeExpr(n.Key) - c.compileTypeExpr(n.Value) -} - -func (c *compiler) compileChanType(n *ast.ChanType) { - c.emitInst(instruction{ - op: opChanType, - value: c.toUint8(n, int(n.Dir)), - }) - c.compileTypeExpr(n.Value) -} - -func (c *compiler) compileCompositeLit(n *ast.CompositeLit) { - if n.Type == nil { - c.emitInstOp(opCompositeLit) - } else { - c.emitInstOp(opTypedCompositeLit) - c.compileTypeExpr(n.Type) - } - for _, elt := range n.Elts { - c.compileExpr(elt) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileFuncLit(n *ast.FuncLit) { - c.emitInstOp(opFuncLit) - c.compileFuncType(n.Type) - c.compileBlockStmt(n.Body) -} - -func (c *compiler) compileEllipsis(n *ast.Ellipsis) { - if n.Elt == nil { - c.emitInstOp(opEllipsis) - } else { - c.emitInstOp(opTypedEllipsis) - c.compileExpr(n.Elt) - } -} - -func (c *compiler) compileKeyValueExpr(n *ast.KeyValueExpr) { - c.emitInstOp(opKeyValueExpr) - c.compileExpr(n.Key) - c.compileExpr(n.Value) -} - -func (c *compiler) compileSelectorExpr(n *ast.SelectorExpr) { - if isWildName(n.Sel.Name) { - c.emitInstOp(opSelectorExpr) - c.compileWildIdent(n.Sel, false) - c.compileExpr(n.X) - return - } - - c.prog.insts = append(c.prog.insts, instruction{ - op: opSimpleSelectorExpr, - valueIndex: c.internString(n.Sel, n.Sel.String()), - }) - c.compileExpr(n.X) -} - -func (c *compiler) compileTypeAssertExpr(n *ast.TypeAssertExpr) { - if n.Type != nil { - c.emitInstOp(opTypeAssertExpr) - c.compileExpr(n.X) - c.compileTypeExpr(n.Type) - } else { - c.emitInstOp(opTypeSwitchAssertExpr) - c.compileExpr(n.X) - } -} - -func (c *compiler) compileStmt(n ast.Stmt) { - switch n := n.(type) { - case *ast.AssignStmt: - c.compileAssignStmt(n) - case *ast.BlockStmt: - c.compileBlockStmt(n) - case *ast.ExprStmt: - c.compileExprStmt(n) - case *ast.IfStmt: - c.compileIfStmt(n) - case *ast.CaseClause: - c.compileCaseClause(n) - case *ast.SwitchStmt: - c.compileSwitchStmt(n) - case *ast.TypeSwitchStmt: - c.compileTypeSwitchStmt(n) - case *ast.SelectStmt: - c.compileSelectStmt(n) - case *ast.ForStmt: - c.compileForStmt(n) - case *ast.RangeStmt: - c.compileRangeStmt(n) - case *ast.IncDecStmt: - c.compileIncDecStmt(n) - case *ast.EmptyStmt: - c.compileEmptyStmt(n) - case *ast.ReturnStmt: - c.compileReturnStmt(n) - case *ast.BranchStmt: - c.compileBranchStmt(n) - case *ast.LabeledStmt: - c.compileLabeledStmt(n) - case *ast.GoStmt: - c.compileGoStmt(n) - case *ast.DeferStmt: - c.compileDeferStmt(n) - case *ast.SendStmt: - c.compileSendStmt(n) - case *ast.DeclStmt: - c.compileDecl(n.Decl) - - default: - panic(c.errorf(n, "compileStmt: unexpected %T", n)) - } -} - -func (c *compiler) compileAssignStmt(n *ast.AssignStmt) { - if len(n.Lhs) == 1 && len(n.Rhs) == 1 { - lhsInfo := decodeWildNode(n.Lhs[0]) - rhsInfo := decodeWildNode(n.Rhs[0]) - if !lhsInfo.Seq && !rhsInfo.Seq { - c.emitInst(instruction{ - op: opAssignStmt, - value: uint8(n.Tok), - }) - c.compileExpr(n.Lhs[0]) - c.compileExpr(n.Rhs[0]) - return - } - } - - c.emitInst(instruction{ - op: opMultiAssignStmt, - value: uint8(n.Tok), - }) - for _, x := range n.Lhs { - c.compileExpr(x) - } - c.emitInstOp(opEnd) - for _, x := range n.Rhs { - c.compileExpr(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileBlockStmt(n *ast.BlockStmt) { - c.emitInstOp(opBlockStmt) - insideStmtList := c.insideStmtList - c.insideStmtList = true - for _, elt := range n.List { - c.compileStmt(elt) - } - c.insideStmtList = insideStmtList - c.emitInstOp(opEnd) -} - -func (c *compiler) compileExprStmt(n *ast.ExprStmt) { - if ident, ok := n.X.(*ast.Ident); ok && isWildName(ident.Name) { - c.compileIdent(ident) - } else { - c.emitInstOp(opExprStmt) - c.compileExpr(n.X) - } -} - -func (c *compiler) compileIfStmt(n *ast.IfStmt) { - // Check for the special case: `if $*_ ...` should match all if statements. - if ident, ok := n.Cond.(*ast.Ident); ok && n.Init == nil && isWildName(ident.Name) { - info := decodeWildName(ident.Name) - if info.Seq && info.Name == "_" { - // Set Init to Cond, change cond from $*_ to $_. - n.Init = &ast.ExprStmt{X: n.Cond} - cond := &ast.Ident{Name: encodeWildName(info.Name, false)} - n.Cond = cond - c.compileIfStmt(n) - return - } - // Named $* is harder and slower. - if info.Seq { - c.prog.insts = append(c.prog.insts, instruction{ - op: pickOp(n.Else == nil, opIfNamedOptStmt, opIfNamedOptElseStmt), - valueIndex: c.internVar(ident, info.Name), - }) - c.compileStmt(n.Body) - if n.Else != nil { - c.compileStmt(n.Else) - } - return - } - } - - switch { - case n.Init == nil && n.Else == nil: - c.emitInstOp(opIfStmt) - c.compileExpr(n.Cond) - c.compileStmt(n.Body) - case n.Init != nil && n.Else == nil: - c.emitInstOp(opIfInitStmt) - c.compileOptStmt(n.Init) - c.compileExpr(n.Cond) - c.compileStmt(n.Body) - case n.Init == nil && n.Else != nil: - c.emitInstOp(opIfElseStmt) - c.compileExpr(n.Cond) - c.compileStmt(n.Body) - c.compileStmt(n.Else) - case n.Init != nil && n.Else != nil: - c.emitInstOp(opIfInitElseStmt) - c.compileOptStmt(n.Init) - c.compileExpr(n.Cond) - c.compileStmt(n.Body) - c.compileStmt(n.Else) - - default: - panic(c.errorf(n, "unexpected if stmt")) - } -} - -func (c *compiler) compileCommClause(n *ast.CommClause) { - c.emitInstOp(pickOp(n.Comm == nil, opDefaultCommClause, opCommClause)) - if n.Comm != nil { - c.compileStmt(n.Comm) - } - for _, x := range n.Body { - c.compileStmt(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileCaseClause(n *ast.CaseClause) { - c.emitInstOp(pickOp(n.List == nil, opDefaultCaseClause, opCaseClause)) - if n.List != nil { - for _, x := range n.List { - c.compileExpr(x) - } - c.emitInstOp(opEnd) - } - for _, x := range n.Body { - c.compileStmt(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileSwitchBody(n *ast.BlockStmt) { - wildcardCase := func(cc *ast.CaseClause) *ast.Ident { - if len(cc.List) != 1 || len(cc.Body) != 1 { - return nil - } - v, ok := cc.List[0].(*ast.Ident) - if !ok || !isWildName(v.Name) { - return nil - } - bodyStmt, ok := cc.Body[0].(*ast.ExprStmt) - if !ok { - return nil - } - bodyIdent, ok := bodyStmt.X.(*ast.Ident) - if !ok || bodyIdent.Name != "gogrep_body" { - return nil - } - return v - } - for _, cc := range n.List { - cc := cc.(*ast.CaseClause) - wildcard := wildcardCase(cc) - if wildcard == nil { - c.compileCaseClause(cc) - continue - } - c.compileWildIdent(wildcard, false) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileSwitchStmt(n *ast.SwitchStmt) { - var op operation - switch { - case n.Init == nil && n.Tag == nil: - op = opSwitchStmt - case n.Init == nil && n.Tag != nil: - op = opSwitchTagStmt - case n.Init != nil && n.Tag == nil: - op = opSwitchInitStmt - default: - op = opSwitchInitTagStmt - } - - c.emitInstOp(op) - if n.Init != nil { - c.compileOptStmt(n.Init) - } - if n.Tag != nil { - c.compileOptExpr(n.Tag) - } - c.compileSwitchBody(n.Body) -} - -func (c *compiler) compileTypeSwitchStmt(n *ast.TypeSwitchStmt) { - c.emitInstOp(pickOp(n.Init == nil, opTypeSwitchStmt, opTypeSwitchInitStmt)) - if n.Init != nil { - c.compileOptStmt(n.Init) - } - c.compileStmt(n.Assign) - c.compileSwitchBody(n.Body) -} - -func (c *compiler) compileSelectStmt(n *ast.SelectStmt) { - c.emitInstOp(opSelectStmt) - - wildcardCase := func(cc *ast.CommClause) *ast.Ident { - if cc.Comm == nil { - return nil - } - vStmt, ok := cc.Comm.(*ast.ExprStmt) - if !ok { - return nil - } - v, ok := vStmt.X.(*ast.Ident) - if !ok || !isWildName(v.Name) { - return nil - } - bodyStmt, ok := cc.Body[0].(*ast.ExprStmt) - if !ok { - return nil - } - bodyIdent, ok := bodyStmt.X.(*ast.Ident) - if !ok || bodyIdent.Name != "gogrep_body" { - return nil - } - return v - } - for _, cc := range n.Body.List { - cc := cc.(*ast.CommClause) - wildcard := wildcardCase(cc) - if wildcard == nil { - c.compileCommClause(cc) - continue - } - c.compileWildIdent(wildcard, false) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileForStmt(n *ast.ForStmt) { - var op operation - switch { - case n.Init == nil && n.Cond == nil && n.Post == nil: - op = opForStmt - case n.Init == nil && n.Cond == nil && n.Post != nil: - op = opForPostStmt - case n.Init == nil && n.Cond != nil && n.Post == nil: - op = opForCondStmt - case n.Init == nil && n.Cond != nil && n.Post != nil: - op = opForCondPostStmt - case n.Init != nil && n.Cond == nil && n.Post == nil: - op = opForInitStmt - case n.Init != nil && n.Cond == nil && n.Post != nil: - op = opForInitPostStmt - case n.Init != nil && n.Cond != nil && n.Post == nil: - op = opForInitCondStmt - default: - op = opForInitCondPostStmt - } - - c.emitInstOp(op) - if n.Init != nil { - c.compileOptStmt(n.Init) - } - if n.Cond != nil { - c.compileOptExpr(n.Cond) - } - if n.Post != nil { - c.compileOptStmt(n.Post) - } - c.compileBlockStmt(n.Body) -} - -func (c *compiler) compileRangeStmt(n *ast.RangeStmt) { - switch { - case n.Key == nil && n.Value == nil: - c.emitInstOp(opRangeStmt) - c.compileExpr(n.X) - c.compileStmt(n.Body) - case n.Key != nil && n.Value == nil: - c.emitInst(instruction{ - op: opRangeKeyStmt, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileExpr(n.Key) - c.compileExpr(n.X) - c.compileStmt(n.Body) - case n.Key != nil && n.Value != nil: - c.emitInst(instruction{ - op: opRangeKeyValueStmt, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileExpr(n.Key) - c.compileExpr(n.Value) - c.compileExpr(n.X) - c.compileStmt(n.Body) - default: - panic(c.errorf(n, "unexpected range stmt")) - } -} - -func (c *compiler) compileIncDecStmt(n *ast.IncDecStmt) { - c.prog.insts = append(c.prog.insts, instruction{ - op: opIncDecStmt, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileExpr(n.X) -} - -func (c *compiler) compileEmptyStmt(n *ast.EmptyStmt) { - _ = n // unused - c.emitInstOp(opEmptyStmt) -} - -func (c *compiler) compileReturnStmt(n *ast.ReturnStmt) { - c.emitInstOp(opReturnStmt) - for _, x := range n.Results { - c.compileExpr(x) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileBranchStmt(n *ast.BranchStmt) { - if n.Label != nil { - if isWildName(n.Label.Name) { - c.prog.insts = append(c.prog.insts, instruction{ - op: opLabeledBranchStmt, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileWildIdent(n.Label, false) - } else { - c.prog.insts = append(c.prog.insts, instruction{ - op: opSimpleLabeledBranchStmt, - value: c.toUint8(n, int(n.Tok)), - valueIndex: c.internString(n.Label, n.Label.Name), - }) - } - return - } - c.prog.insts = append(c.prog.insts, instruction{ - op: opBranchStmt, - value: c.toUint8(n, int(n.Tok)), - }) -} - -func (c *compiler) compileLabeledStmt(n *ast.LabeledStmt) { - if isWildName(n.Label.Name) { - c.emitInstOp(opLabeledStmt) - c.compileWildIdent(n.Label, false) - c.compileStmt(n.Stmt) - return - } - - c.prog.insts = append(c.prog.insts, instruction{ - op: opSimpleLabeledStmt, - valueIndex: c.internString(n.Label, n.Label.Name), - }) - c.compileStmt(n.Stmt) -} - -func (c *compiler) compileGoStmt(n *ast.GoStmt) { - c.emitInstOp(opGoStmt) - c.compileExpr(n.Call) -} - -func (c *compiler) compileDeferStmt(n *ast.DeferStmt) { - c.emitInstOp(opDeferStmt) - c.compileExpr(n.Call) -} - -func (c *compiler) compileSendStmt(n *ast.SendStmt) { - c.emitInstOp(opSendStmt) - c.compileExpr(n.Chan) - c.compileExpr(n.Value) -} - -func (c *compiler) compileDeclSlice(decls []ast.Decl) { - c.emitInstOp(opMultiDecl) - for _, n := range decls { - c.compileDecl(n) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileStmtSlice(stmts []ast.Stmt) { - c.emitInstOp(opMultiStmt) - insideStmtList := c.insideStmtList - c.insideStmtList = true - for _, n := range stmts { - c.compileStmt(n) - } - c.insideStmtList = insideStmtList - c.emitInstOp(opEnd) -} - -func (c *compiler) compileExprSlice(exprs []ast.Expr) { - c.emitInstOp(opMultiExpr) - for _, n := range exprs { - c.compileExpr(n) - } - c.emitInstOp(opEnd) -} - -func (c *compiler) compileRangeClause(clause *rangeClause) { - c.emitInstOp(opRangeClause) - c.compileExpr(clause.X) -} - -func (c *compiler) compileRangeHeader(h *rangeHeader) { - n := h.Node - switch { - case n.Key == nil && n.Value == nil: - c.emitInstOp(opRangeHeader) - c.compileExpr(n.X) - case n.Key != nil && n.Value == nil: - c.emitInst(instruction{ - op: opRangeKeyHeader, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileExpr(n.Key) - c.compileExpr(n.X) - case n.Key != nil && n.Value != nil: - c.emitInst(instruction{ - op: opRangeKeyValueHeader, - value: c.toUint8(n, int(n.Tok)), - }) - c.compileExpr(n.Key) - c.compileExpr(n.Value) - c.compileExpr(n.X) - default: - panic(c.errorf(n, "unexpected range header")) - } -} - -func pickOp(cond bool, ifTrue, ifFalse operation) operation { - if cond { - return ifTrue - } - return ifFalse -} - -func fitsUint8(v int) bool { - return v >= 0 && v <= 0xff -} diff --git a/vendor/github.com/quasilyte/gogrep/compile_import.go b/vendor/github.com/quasilyte/gogrep/compile_import.go deleted file mode 100644 index ab0dd12a7..000000000 --- a/vendor/github.com/quasilyte/gogrep/compile_import.go +++ /dev/null @@ -1,57 +0,0 @@ -package gogrep - -import ( - "errors" - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -func compileImportPattern(config CompileConfig) (*Pattern, PatternInfo, error) { - // TODO: figure out how to compile it as a part of a normal pattern compilation? - // This is an adhoc solution to a problem. - - readIdent := func(s string) (varname, rest string) { - first := true - var offset int - for _, ch := range s { - ok := unicode.IsLetter(ch) || - ch == '_' || - (!first && unicode.IsDigit(ch)) - if !ok { - break - } - offset += utf8.RuneLen(ch) - first = false - } - return s[:offset], s[offset:] - } - - info := newPatternInfo() - src := config.Src - src = src[len("import $"):] - if src == "" { - return nil, info, errors.New("expected ident after $, found EOF") - } - varname, rest := readIdent(src) - if strings.TrimSpace(rest) != "" { - return nil, info, fmt.Errorf("unexpected %s", rest) - } - var p program - if varname != "_" { - info.Vars[src] = struct{}{} - p.strings = []string{varname} - p.insts = []instruction{ - {op: opImportDecl}, - {op: opNamedNodeSeq, valueIndex: 0}, - {op: opEnd}, - } - } else { - p.insts = []instruction{ - {op: opAnyImportDecl}, - } - } - m := matcher{prog: &p, insts: p.insts} - return &Pattern{m: &m}, info, nil -} diff --git a/vendor/github.com/quasilyte/gogrep/gen_operations.go b/vendor/github.com/quasilyte/gogrep/gen_operations.go deleted file mode 100644 index fd8035774..000000000 --- a/vendor/github.com/quasilyte/gogrep/gen_operations.go +++ /dev/null @@ -1,366 +0,0 @@ -//go:build main -// +build main - -package main - -import ( - "bytes" - "fmt" - "go/format" - "io/ioutil" - "log" - "strings" - "text/template" -) - -var opPrototypes = []operationProto{ - {name: "Node", tag: "Node"}, - {name: "NamedNode", tag: "Node", valueIndex: "strings | wildcard name"}, - {name: "NodeSeq"}, - {name: "NamedNodeSeq", valueIndex: "strings | wildcard name"}, - {name: "OptNode"}, - {name: "NamedOptNode", valueIndex: "strings | wildcard name"}, - - {name: "FieldNode", tag: "Node"}, - {name: "NamedFieldNode", tag: "Node", valueIndex: "strings | wildcard name"}, - - {name: "MultiStmt", tag: "StmtList", args: "stmts...", example: "f(); g()"}, - {name: "MultiExpr", tag: "ExprList", args: "exprs...", example: "f(), g()"}, - {name: "MultiDecl", tag: "DeclList", args: "exprs...", example: "f(), g()"}, - - {name: "End"}, - - {name: "BasicLit", tag: "BasicLit", valueIndex: "ifaces | parsed literal value"}, - {name: "StrictIntLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, - {name: "StrictFloatLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, - {name: "StrictCharLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, - {name: "StrictStringLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, - {name: "StrictComplexLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, - - {name: "Ident", tag: "Ident", valueIndex: "strings | ident name"}, - {name: "Pkg", tag: "Ident", valueIndex: "strings | package path"}, - - {name: "IndexExpr", tag: "IndexExpr", args: "x expr"}, - - {name: "IndexListExpr", tag: "IndexListExpr", args: "x exprs..."}, - - {name: "SliceExpr", tag: "SliceExpr", args: "x"}, - {name: "SliceFromExpr", tag: "SliceExpr", args: "x from", example: "x[from:]"}, - {name: "SliceToExpr", tag: "SliceExpr", args: "x to", example: "x[:to]"}, - {name: "SliceFromToExpr", tag: "SliceExpr", args: "x from to", example: "x[from:to]"}, - {name: "SliceToCapExpr", tag: "SliceExpr", args: "x from cap", example: "x[:from:cap]"}, - {name: "SliceFromToCapExpr", tag: "SliceExpr", args: "x from to cap", example: "x[from:to:cap]"}, - - {name: "FuncLit", tag: "FuncLit", args: "type block"}, - - {name: "CompositeLit", tag: "CompositeLit", args: "elts...", example: "{elts...}"}, - {name: "TypedCompositeLit", tag: "CompositeLit", args: "typ elts...", example: "typ{elts...}"}, - - {name: "SimpleSelectorExpr", tag: "SelectorExpr", args: "x", valueIndex: "strings | selector name"}, - {name: "SelectorExpr", tag: "SelectorExpr", args: "x sel"}, - {name: "TypeAssertExpr", tag: "TypeAssertExpr", args: "x typ"}, - {name: "TypeSwitchAssertExpr", tag: "TypeAssertExpr", args: "x"}, - - {name: "StructType", tag: "StructType", args: "fields"}, - {name: "InterfaceType", tag: "InterfaceType", args: "fields"}, - {name: "EfaceType", tag: "InterfaceType"}, - {name: "VoidFuncType", tag: "FuncType", args: "params"}, - {name: "GenericVoidFuncType", tag: "FuncType", args: "typeparams params"}, - {name: "FuncType", tag: "FuncType", args: "params results"}, - {name: "GenericFuncType", tag: "FuncType", args: "typeparams params results"}, - {name: "ArrayType", tag: "ArrayType", args: "length elem"}, - {name: "SliceType", tag: "ArrayType", args: "elem"}, - {name: "MapType", tag: "MapType", args: "key value"}, - {name: "ChanType", tag: "ChanType", args: "value", value: "ast.ChanDir | channel direction"}, - {name: "KeyValueExpr", tag: "KeyValueExpr", args: "key value"}, - - {name: "Ellipsis", tag: "Ellipsis"}, - {name: "TypedEllipsis", tag: "Ellipsis", args: "type"}, - - {name: "StarExpr", tag: "StarExpr", args: "x"}, - {name: "UnaryExpr", tag: "UnaryExpr", args: "x", value: "token.Token | unary operator"}, - {name: "BinaryExpr", tag: "BinaryExpr", args: "x y", value: "token.Token | binary operator"}, - {name: "ParenExpr", tag: "ParenExpr", args: "x"}, - - { - name: "ArgList", - args: "exprs...", - example: "1, 2, 3", - }, - { - name: "SimpleArgList", - note: "Like ArgList, but pattern contains no $*", - args: "exprs[]", - value: "int | slice len", - example: "1, 2, 3", - }, - - {name: "VariadicCallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs...)"}, - {name: "NonVariadicCallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs)"}, - {name: "MaybeVariadicCallExpr", tag: "CallExpr", args: "fn args", value: "int | can be variadic if len(args)>value", example: "f(1, xs) or f(1, xs...)"}, - {name: "CallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs) or f(1, xs...)"}, - - {name: "AssignStmt", tag: "AssignStmt", args: "lhs rhs", value: "token.Token | ':=' or '='", example: "lhs := rhs()"}, - {name: "MultiAssignStmt", tag: "AssignStmt", args: "lhs... rhs...", value: "token.Token | ':=' or '='", example: "lhs1, lhs2 := rhs()"}, - - {name: "BranchStmt", tag: "BranchStmt", args: "x", value: "token.Token | branch kind"}, - {name: "SimpleLabeledBranchStmt", tag: "BranchStmt", args: "x", valueIndex: "strings | label name", value: "token.Token | branch kind"}, - {name: "LabeledBranchStmt", tag: "BranchStmt", args: "label x", value: "token.Token | branch kind"}, - {name: "SimpleLabeledStmt", tag: "LabeledStmt", args: "x", valueIndex: "strings | label name"}, - {name: "LabeledStmt", tag: "LabeledStmt", args: "label x"}, - - {name: "BlockStmt", tag: "BlockStmt", args: "body..."}, - {name: "ExprStmt", tag: "ExprStmt", args: "x"}, - - {name: "GoStmt", tag: "GoStmt", args: "x"}, - {name: "DeferStmt", tag: "DeferStmt", args: "x"}, - - {name: "SendStmt", tag: "SendStmt", args: "ch value"}, - - {name: "EmptyStmt", tag: "EmptyStmt"}, - {name: "IncDecStmt", tag: "IncDecStmt", args: "x", value: "token.Token | '++' or '--'"}, - {name: "ReturnStmt", tag: "ReturnStmt", args: "results..."}, - - {name: "IfStmt", tag: "IfStmt", args: "cond block", example: "if cond {}"}, - {name: "IfInitStmt", tag: "IfStmt", args: "init cond block", example: "if init; cond {}"}, - {name: "IfElseStmt", tag: "IfStmt", args: "cond block else", example: "if cond {} else ..."}, - {name: "IfInitElseStmt", tag: "IfStmt", args: "init cond block else", example: "if init; cond {} else ..."}, - {name: "IfNamedOptStmt", tag: "IfStmt", args: "block", valueIndex: "strings | wildcard name", example: "if $*x {}"}, - {name: "IfNamedOptElseStmt", tag: "IfStmt", args: "block else", valueIndex: "strings | wildcard name", example: "if $*x {} else ..."}, - - {name: "SwitchStmt", tag: "SwitchStmt", args: "body...", example: "switch {}"}, - {name: "SwitchTagStmt", tag: "SwitchStmt", args: "tag body...", example: "switch tag {}"}, - {name: "SwitchInitStmt", tag: "SwitchStmt", args: "init body...", example: "switch init; {}"}, - {name: "SwitchInitTagStmt", tag: "SwitchStmt", args: "init tag body...", example: "switch init; tag {}"}, - - {name: "SelectStmt", tag: "SelectStmt", args: "body..."}, - - {name: "TypeSwitchStmt", tag: "TypeSwitchStmt", args: "x block", example: "switch x.(type) {}"}, - {name: "TypeSwitchInitStmt", tag: "TypeSwitchStmt", args: "init x block", example: "switch init; x.(type) {}"}, - - {name: "CaseClause", tag: "CaseClause", args: "values... body..."}, - {name: "DefaultCaseClause", tag: "CaseClause", args: "body..."}, - - {name: "CommClause", tag: "CommClause", args: "comm body..."}, - {name: "DefaultCommClause", tag: "CommClause", args: "body..."}, - - {name: "ForStmt", tag: "ForStmt", args: "blocl", example: "for {}"}, - {name: "ForPostStmt", tag: "ForStmt", args: "post block", example: "for ; ; post {}"}, - {name: "ForCondStmt", tag: "ForStmt", args: "cond block", example: "for ; cond; {}"}, - {name: "ForCondPostStmt", tag: "ForStmt", args: "cond post block", example: "for ; cond; post {}"}, - {name: "ForInitStmt", tag: "ForStmt", args: "init block", example: "for init; ; {}"}, - {name: "ForInitPostStmt", tag: "ForStmt", args: "init post block", example: "for init; ; post {}"}, - {name: "ForInitCondStmt", tag: "ForStmt", args: "init cond block", example: "for init; cond; {}"}, - {name: "ForInitCondPostStmt", tag: "ForStmt", args: "init cond post block", example: "for init; cond; post {}"}, - - {name: "RangeStmt", tag: "RangeStmt", args: "x block", example: "for range x {}"}, - {name: "RangeKeyStmt", tag: "RangeStmt", args: "key x block", value: "token.Token | ':=' or '='", example: "for key := range x {}"}, - {name: "RangeKeyValueStmt", tag: "RangeStmt", args: "key value x block", value: "token.Token | ':=' or '='", example: "for key, value := range x {}"}, - - {name: "RangeClause", tag: "RangeStmt", args: "x", example: "range x"}, - {name: "RangeHeader", tag: "RangeStmt", args: "x", example: "for range x"}, - {name: "RangeKeyHeader", tag: "RangeStmt", args: "key x", value: "token.Token | ':=' or '='", example: "for key := range x"}, - {name: "RangeKeyValueHeader", tag: "RangeStmt", args: "key value x", value: "token.Token | ':=' or '='", example: "for key, value := range x"}, - - {name: "FieldList", args: "fields..."}, - {name: "UnnamedField", args: "typ", example: "type"}, - {name: "SimpleField", args: "typ", valueIndex: "strings | field name", example: "name type"}, - {name: "Field", args: "name typ", example: "$name type"}, - {name: "MultiField", args: "names... typ", example: "name1, name2 type"}, - - {name: "ValueSpec", tag: "ValueSpec", args: "value"}, - {name: "ValueInitSpec", tag: "ValueSpec", args: "lhs... rhs...", example: "lhs = rhs"}, - {name: "TypedValueInitSpec", tag: "ValueSpec", args: "lhs... type rhs...", example: "lhs typ = rhs"}, - {name: "TypedValueSpec", tag: "ValueSpec", args: "lhs... type", example: "lhs typ"}, - - {name: "SimpleTypeSpec", tag: "TypeSpec", args: "type", valueIndex: "strings | type name", example: "name type"}, - {name: "TypeSpec", tag: "TypeSpec", args: "name type", example: "name type"}, - {name: "GenericTypeSpec", tag: "TypeSpec", args: "name typeparasm type", example: "name[typeparams] type"}, - {name: "TypeAliasSpec", tag: "TypeSpec", args: "name type", example: "name = type"}, - - {name: "SimpleFuncDecl", tag: "FuncDecl", args: "type block", valueIndex: "strings | field name"}, - {name: "FuncDecl", tag: "FuncDecl", args: "name type block"}, - {name: "MethodDecl", tag: "FuncDecl", args: "recv name type block"}, - {name: "FuncProtoDecl", tag: "FuncDecl", args: "name type"}, - {name: "MethodProtoDecl", tag: "FuncDecl", args: "recv name type"}, - - {name: "DeclStmt", tag: "DeclStmt", args: "decl"}, - {name: "ConstDecl", tag: "GenDecl", args: "valuespecs..."}, - {name: "VarDecl", tag: "GenDecl", args: "valuespecs..."}, - {name: "TypeDecl", tag: "GenDecl", args: "typespecs..."}, - - {name: "AnyImportDecl", tag: "GenDecl"}, - {name: "ImportDecl", tag: "GenDecl", args: "importspecs..."}, - - {name: "EmptyPackage", tag: "File", args: "name"}, -} - -type operationProto struct { - name string - value string - valueIndex string - tag string - example string - args string - note string -} - -type operationInfo struct { - Example string - Note string - Args string - Enum uint8 - TagName string - Name string - ValueDoc string - ValueIndexDoc string - ExtraValueKindName string - ValueKindName string - VariadicMap uint64 - NumArgs int - SliceIndex int -} - -const stackUnchanged = "" - -var fileTemplate = template.Must(template.New("operations.go").Parse(`// Code generated "gen_operations.go"; DO NOT EDIT. - -package gogrep - -import ( - "github.com/quasilyte/gogrep/nodetag" -) - -//go:generate stringer -type=operation -trimprefix=op -type operation uint8 - -const ( - opInvalid operation = 0 -{{ range .Operations }} - // Tag: {{.TagName}} - {{- if .Note}}{{print "\n"}}// {{.Note}}{{end}} - {{- if .Args}}{{print "\n"}}// Args: {{.Args}}{{end}} - {{- if .Example}}{{print "\n"}}// Example: {{.Example}}{{end}} - {{- if .ValueDoc}}{{print "\n"}}// Value: {{.ValueDoc}}{{end}} - {{- if .ValueIndexDoc}}{{print "\n"}}// ValueIndex: {{.ValueIndexDoc}}{{end}} - op{{ .Name }} operation = {{.Enum}} -{{ end -}} -) - -type operationInfo struct { - Tag nodetag.Value - NumArgs int - ValueKind valueKind - ExtraValueKind valueKind - VariadicMap bitmap64 - SliceIndex int -} - -var operationInfoTable = [256]operationInfo{ - opInvalid: {}, - -{{ range .Operations -}} - op{{.Name}}: { - Tag: nodetag.{{.TagName}}, - NumArgs: {{.NumArgs}}, - ValueKind: {{.ValueKindName}}, - ExtraValueKind: {{.ExtraValueKindName}}, - VariadicMap: {{.VariadicMap}}, // {{printf "%b" .VariadicMap}} - SliceIndex: {{.SliceIndex}}, - }, -{{ end }} -} -`)) - -func main() { - operations := make([]operationInfo, len(opPrototypes)) - for i, proto := range opPrototypes { - enum := uint8(i + 1) - - tagName := proto.tag - if tagName == "" { - tagName = "Unknown" - } - - variadicMap := uint64(0) - numArgs := 0 - sliceLenIndex := -1 - if proto.args != "" { - args := strings.Split(proto.args, " ") - numArgs = len(args) - for i, arg := range args { - isVariadic := strings.HasSuffix(arg, "...") - if isVariadic { - variadicMap |= 1 << i - } - if strings.HasSuffix(arg, "[]") { - sliceLenIndex = i - } - } - } - - extraValueKindName := "emptyValue" - if proto.valueIndex != "" { - parts := strings.Split(proto.valueIndex, " | ") - typ := parts[0] - switch typ { - case "strings": - extraValueKindName = "stringValue" - case "ifaces": - extraValueKindName = "ifaceValue" - default: - panic(fmt.Sprintf("%s: unexpected %s type", proto.name, typ)) - } - } - valueKindName := "emptyValue" - if proto.value != "" { - parts := strings.Split(proto.value, " | ") - typ := parts[0] - switch typ { - case "token.Token": - valueKindName = "tokenValue" - case "ast.ChanDir": - valueKindName = "chandirValue" - case "int": - valueKindName = "intValue" - default: - panic(fmt.Sprintf("%s: unexpected %s type", proto.name, typ)) - } - } - - operations[i] = operationInfo{ - Example: proto.example, - Note: proto.note, - Args: proto.args, - Enum: enum, - TagName: tagName, - Name: proto.name, - ValueDoc: proto.value, - ValueIndexDoc: proto.valueIndex, - NumArgs: numArgs, - VariadicMap: variadicMap, - ExtraValueKindName: extraValueKindName, - ValueKindName: valueKindName, - SliceIndex: sliceLenIndex, - } - } - - var buf bytes.Buffer - err := fileTemplate.Execute(&buf, map[string]interface{}{ - "Operations": operations, - }) - if err != nil { - log.Panicf("execute template: %v", err) - } - writeFile("operations.gen.go", buf.Bytes()) -} - -func writeFile(filename string, data []byte) { - pretty, err := format.Source(data) - if err != nil { - log.Panicf("gofmt: %v", err) - } - if err := ioutil.WriteFile(filename, pretty, 0666); err != nil { - log.Panicf("write %s: %v", filename, err) - } -} diff --git a/vendor/github.com/quasilyte/gogrep/gogrep.go b/vendor/github.com/quasilyte/gogrep/gogrep.go deleted file mode 100644 index 47a03f9b4..000000000 --- a/vendor/github.com/quasilyte/gogrep/gogrep.go +++ /dev/null @@ -1,187 +0,0 @@ -package gogrep - -import ( - "errors" - "go/ast" - "go/token" - "go/types" - "strings" - - "github.com/quasilyte/gogrep/nodetag" -) - -func IsEmptyNodeSlice(n ast.Node) bool { - if list, ok := n.(*NodeSlice); ok { - return list.Len() == 0 - } - return false -} - -// MatchData describes a successful pattern match. -type MatchData struct { - Node ast.Node - Capture []CapturedNode -} - -type CapturedNode struct { - Name string - Node ast.Node -} - -func (data MatchData) CapturedByName(name string) (ast.Node, bool) { - if name == "$$" { - return data.Node, true - } - return findNamed(data.Capture, name) -} - -type PartialNode struct { - X ast.Node - - from token.Pos - to token.Pos -} - -func (p *PartialNode) Pos() token.Pos { return p.from } -func (p *PartialNode) End() token.Pos { return p.to } - -type MatcherState struct { - Types *types.Info - - // CapturePreset is a key-value pairs to use in the next match calls - // as predefined variables. - // For example, if the pattern is `$x = f()` and CapturePreset contains - // a pair with Name=x and value of `obj.x`, then the above mentioned - // pattern will only match `obj.x = f()` statements. - // - // If nil, the default behavior will be used. A first syntax element - // matching the matcher var will be captured. - CapturePreset []CapturedNode - - // node values recorded by name, excluding "_" (used only by the - // actual matching phase) - capture []CapturedNode - - nodeSlices []NodeSlice - nodeSlicesUsed int - - pc int - - partial PartialNode -} - -func NewMatcherState() MatcherState { - return MatcherState{ - capture: make([]CapturedNode, 0, 8), - nodeSlices: make([]NodeSlice, 16), - } -} - -type Pattern struct { - m *matcher -} - -type PatternInfo struct { - Vars map[string]struct{} -} - -func (p *Pattern) NodeTag() nodetag.Value { - return operationInfoTable[p.m.prog.insts[0].op].Tag -} - -// MatchNode calls cb if n matches a pattern. -func (p *Pattern) MatchNode(state *MatcherState, n ast.Node, cb func(MatchData)) { - p.m.MatchNode(state, n, cb) -} - -// Clone creates a pattern copy. -func (p *Pattern) Clone() *Pattern { - clone := *p - clone.m = &matcher{} - *clone.m = *p.m - return &clone -} - -type CompileConfig struct { - Fset *token.FileSet - - // Src is a gogrep pattern expression string. - Src string - - // When strict is false, gogrep may consider 0xA and 10 to be identical. - // If true, a compiled pattern will require a full syntax match. - Strict bool - - // WithTypes controls whether gogrep would have types.Info during the pattern execution. - // If set to true, it will compile a pattern to a potentially more precise form, where - // fmt.Printf maps to the stdlib function call but not Printf method call on some - // random fmt variable. - WithTypes bool - - // Imports specifies packages that should be recognized for the type-aware matching. - // It maps a package name to a package path. - // Only used if WithTypes is true. - Imports map[string]string -} - -func Compile(config CompileConfig) (*Pattern, PatternInfo, error) { - if strings.HasPrefix(config.Src, "import $") { - return compileImportPattern(config) - } - info := newPatternInfo() - n, err := parseExpr(config.Fset, config.Src) - if err != nil { - return nil, info, err - } - if n == nil { - return nil, info, errors.New("invalid pattern syntax") - } - var c compiler - c.config = config - prog, err := c.Compile(n, &info) - if err != nil { - return nil, info, err - } - m := newMatcher(prog) - return &Pattern{m: m}, info, nil -} - -func Walk(root ast.Node, fn func(n ast.Node) bool) { - if root, ok := root.(*NodeSlice); ok { - switch root.Kind { - case ExprNodeSlice: - for _, e := range root.exprSlice { - ast.Inspect(e, fn) - } - case StmtNodeSlice: - for _, e := range root.stmtSlice { - ast.Inspect(e, fn) - } - case FieldNodeSlice: - for _, e := range root.fieldSlice { - ast.Inspect(e, fn) - } - case IdentNodeSlice: - for _, e := range root.identSlice { - ast.Inspect(e, fn) - } - case SpecNodeSlice: - for _, e := range root.specSlice { - ast.Inspect(e, fn) - } - default: - for _, e := range root.declSlice { - ast.Inspect(e, fn) - } - } - return - } - - ast.Inspect(root, fn) -} - -func newPatternInfo() PatternInfo { - return PatternInfo{ - Vars: make(map[string]struct{}), - } -} diff --git a/vendor/github.com/quasilyte/gogrep/instructions.go b/vendor/github.com/quasilyte/gogrep/instructions.go deleted file mode 100644 index 9f4f72d88..000000000 --- a/vendor/github.com/quasilyte/gogrep/instructions.go +++ /dev/null @@ -1,116 +0,0 @@ -package gogrep - -import ( - "fmt" - "go/ast" - "go/token" - "strings" -) - -type bitmap64 uint64 - -func (m bitmap64) IsSet(pos int) bool { - return m&(1<= sliceLen { - break - } - } -} - -func (m *matcher) matchNamed(state *MatcherState, name string, n ast.Node) bool { - prev, ok := findNamed(state.capture, name) - if !ok { - // First occurrence, record value. - state.capture = append(state.capture, CapturedNode{Name: name, Node: n}) - return true - } - - return equalNodes(prev, n) -} - -func (m *matcher) matchNamedField(state *MatcherState, name string, n ast.Node) bool { - prev, ok := findNamed(state.capture, name) - if !ok { - // First occurrence, record value. - unwrapped := m.unwrapNode(n) - state.capture = append(state.capture, CapturedNode{Name: name, Node: unwrapped}) - return true - } - n = m.unwrapNode(n) - return equalNodes(prev, n) -} - -func (m *matcher) unwrapNode(x ast.Node) ast.Node { - switch x := x.(type) { - case *ast.Field: - if len(x.Names) == 0 { - return x.Type - } - case *ast.FieldList: - if x != nil && len(x.List) == 1 && len(x.List[0].Names) == 0 { - return x.List[0].Type - } - } - return x -} - -func (m *matcher) matchNodeWithInst(state *MatcherState, inst instruction, n ast.Node) bool { - switch inst.op { - case opNode: - return n != nil - case opOptNode: - return true - - case opNamedNode: - return n != nil && m.matchNamed(state, m.stringValue(inst), n) - case opNamedOptNode: - return m.matchNamed(state, m.stringValue(inst), n) - - case opFieldNode: - n, ok := n.(*ast.FieldList) - return ok && n != nil && len(n.List) == 1 && len(n.List[0].Names) == 0 - case opNamedFieldNode: - return n != nil && m.matchNamedField(state, m.stringValue(inst), n) - - case opBasicLit: - n, ok := n.(*ast.BasicLit) - return ok && m.ifaceValue(inst) == literalValue(n) - - case opStrictIntLit: - n, ok := n.(*ast.BasicLit) - return ok && n.Kind == token.INT && m.stringValue(inst) == n.Value - case opStrictFloatLit: - n, ok := n.(*ast.BasicLit) - return ok && n.Kind == token.FLOAT && m.stringValue(inst) == n.Value - case opStrictCharLit: - n, ok := n.(*ast.BasicLit) - return ok && n.Kind == token.CHAR && m.stringValue(inst) == n.Value - case opStrictStringLit: - n, ok := n.(*ast.BasicLit) - return ok && n.Kind == token.STRING && m.stringValue(inst) == n.Value - case opStrictComplexLit: - n, ok := n.(*ast.BasicLit) - return ok && n.Kind == token.IMAG && m.stringValue(inst) == n.Value - - case opIdent: - n, ok := n.(*ast.Ident) - return ok && m.stringValue(inst) == n.Name - - case opPkg: - n, ok := n.(*ast.Ident) - if !ok { - return false - } - obj := state.Types.ObjectOf(n) - if obj == nil { - return false - } - pkgName, ok := obj.(*types.PkgName) - return ok && pkgName.Imported().Path() == m.stringValue(inst) - - case opBinaryExpr: - n, ok := n.(*ast.BinaryExpr) - return ok && n.Op == token.Token(inst.value) && - m.matchNode(state, n.X) && m.matchNode(state, n.Y) - - case opUnaryExpr: - n, ok := n.(*ast.UnaryExpr) - return ok && n.Op == token.Token(inst.value) && m.matchNode(state, n.X) - - case opStarExpr: - n, ok := n.(*ast.StarExpr) - return ok && m.matchNode(state, n.X) - - case opVariadicCallExpr: - n, ok := n.(*ast.CallExpr) - return ok && n.Ellipsis.IsValid() && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) - case opNonVariadicCallExpr: - n, ok := n.(*ast.CallExpr) - return ok && !n.Ellipsis.IsValid() && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) - case opMaybeVariadicCallExpr: - n, ok := n.(*ast.CallExpr) - if !ok { - return false - } - if n.Ellipsis.IsValid() && len(n.Args) <= int(inst.value) { - return false - } - return m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) - case opCallExpr: - n, ok := n.(*ast.CallExpr) - return ok && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) - - case opSimpleSelectorExpr: - n, ok := n.(*ast.SelectorExpr) - return ok && m.stringValue(inst) == n.Sel.Name && m.matchNode(state, n.X) - case opSelectorExpr: - n, ok := n.(*ast.SelectorExpr) - return ok && m.matchNode(state, n.Sel) && m.matchNode(state, n.X) - - case opTypeAssertExpr: - n, ok := n.(*ast.TypeAssertExpr) - return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Type) - case opTypeSwitchAssertExpr: - n, ok := n.(*ast.TypeAssertExpr) - return ok && n.Type == nil && m.matchNode(state, n.X) - - case opSliceExpr: - n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && n.High == nil && m.matchNode(state, n.X) - case opSliceFromExpr: - n, ok := n.(*ast.SliceExpr) - return ok && n.High == nil && !n.Slice3 && - m.matchNode(state, n.X) && m.matchNode(state, n.Low) - case opSliceToExpr: - n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && !n.Slice3 && - m.matchNode(state, n.X) && m.matchNode(state, n.High) - case opSliceFromToExpr: - n, ok := n.(*ast.SliceExpr) - return ok && !n.Slice3 && - m.matchNode(state, n.X) && m.matchNode(state, n.Low) && m.matchNode(state, n.High) - case opSliceToCapExpr: - n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && - m.matchNode(state, n.X) && m.matchNode(state, n.High) && m.matchNode(state, n.Max) - case opSliceFromToCapExpr: - n, ok := n.(*ast.SliceExpr) - return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Low) && m.matchNode(state, n.High) && m.matchNode(state, n.Max) - - case opIndexExpr: - n, ok := n.(*ast.IndexExpr) - return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Index) - - case opIndexListExpr: - n, ok := n.(*typeparams.IndexListExpr) - return ok && m.matchNode(state, n.X) && m.matchExprSlice(state, n.Indices) - - case opKeyValueExpr: - n, ok := n.(*ast.KeyValueExpr) - return ok && m.matchNode(state, n.Key) && m.matchNode(state, n.Value) - - case opParenExpr: - n, ok := n.(*ast.ParenExpr) - return ok && m.matchNode(state, n.X) - - case opEllipsis: - n, ok := n.(*ast.Ellipsis) - return ok && n.Elt == nil - case opTypedEllipsis: - n, ok := n.(*ast.Ellipsis) - return ok && n.Elt != nil && m.matchNode(state, n.Elt) - - case opSliceType: - n, ok := n.(*ast.ArrayType) - return ok && n.Len == nil && m.matchNode(state, n.Elt) - case opArrayType: - n, ok := n.(*ast.ArrayType) - return ok && n.Len != nil && m.matchNode(state, n.Len) && m.matchNode(state, n.Elt) - case opMapType: - n, ok := n.(*ast.MapType) - return ok && m.matchNode(state, n.Key) && m.matchNode(state, n.Value) - case opChanType: - n, ok := n.(*ast.ChanType) - return ok && ast.ChanDir(inst.value) == n.Dir && m.matchNode(state, n.Value) - case opVoidFuncType: - n, ok := n.(*ast.FuncType) - return ok && n.Results == nil && m.matchNode(state, n.Params) - case opGenericVoidFuncType: - n, ok := n.(*ast.FuncType) - return ok && n.Results == nil && m.matchNode(state, typeparams.ForFuncType(n)) && m.matchNode(state, n.Params) - case opFuncType: - n, ok := n.(*ast.FuncType) - return ok && m.matchNode(state, n.Params) && m.matchNode(state, n.Results) - case opGenericFuncType: - n, ok := n.(*ast.FuncType) - return ok && m.matchNode(state, typeparams.ForFuncType(n)) && m.matchNode(state, n.Params) && m.matchNode(state, n.Results) - case opStructType: - n, ok := n.(*ast.StructType) - return ok && m.matchNode(state, n.Fields) - case opInterfaceType: - n, ok := n.(*ast.InterfaceType) - return ok && m.matchNode(state, n.Methods) - case opEfaceType: - switch n := n.(type) { - case *ast.InterfaceType: - return len(n.Methods.List) == 0 - case *ast.Ident: - return n.Name == "any" - default: - return false - } - - case opCompositeLit: - n, ok := n.(*ast.CompositeLit) - return ok && n.Type == nil && m.matchExprSlice(state, n.Elts) - case opTypedCompositeLit: - n, ok := n.(*ast.CompositeLit) - return ok && n.Type != nil && m.matchNode(state, n.Type) && m.matchExprSlice(state, n.Elts) - - case opUnnamedField: - n, ok := n.(*ast.Field) - return ok && len(n.Names) == 0 && m.matchNode(state, n.Type) - case opSimpleField: - n, ok := n.(*ast.Field) - return ok && len(n.Names) == 1 && m.stringValue(inst) == n.Names[0].Name && m.matchNode(state, n.Type) - case opField: - n, ok := n.(*ast.Field) - return ok && len(n.Names) == 1 && m.matchNode(state, n.Names[0]) && m.matchNode(state, n.Type) - case opMultiField: - n, ok := n.(*ast.Field) - return ok && len(n.Names) >= 2 && m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) - case opFieldList: - // FieldList could be nil in places like function return types. - n, ok := n.(*ast.FieldList) - return ok && n != nil && m.matchFieldSlice(state, n.List) - - case opFuncLit: - n, ok := n.(*ast.FuncLit) - return ok && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) - - case opAssignStmt: - n, ok := n.(*ast.AssignStmt) - return ok && token.Token(inst.value) == n.Tok && - len(n.Lhs) == 1 && m.matchNode(state, n.Lhs[0]) && - len(n.Rhs) == 1 && m.matchNode(state, n.Rhs[0]) - case opMultiAssignStmt: - n, ok := n.(*ast.AssignStmt) - return ok && token.Token(inst.value) == n.Tok && - m.matchExprSlice(state, n.Lhs) && m.matchExprSlice(state, n.Rhs) - - case opExprStmt: - n, ok := n.(*ast.ExprStmt) - return ok && m.matchNode(state, n.X) - - case opGoStmt: - n, ok := n.(*ast.GoStmt) - return ok && m.matchNode(state, n.Call) - case opDeferStmt: - n, ok := n.(*ast.DeferStmt) - return ok && m.matchNode(state, n.Call) - case opSendStmt: - n, ok := n.(*ast.SendStmt) - return ok && m.matchNode(state, n.Chan) && m.matchNode(state, n.Value) - - case opBlockStmt: - n, ok := n.(*ast.BlockStmt) - return ok && m.matchStmtSlice(state, n.List) - - case opIfStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Init == nil && n.Else == nil && - m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) - case opIfElseStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Init == nil && n.Else != nil && - m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) - case opIfInitStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Else == nil && - m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) - case opIfInitElseStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Else != nil && - m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) - - case opIfNamedOptStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Else == nil && m.matchNode(state, n.Body) && - m.matchNamed(state, m.stringValue(inst), m.toStmtSlice(state, n.Cond, n.Init)) - case opIfNamedOptElseStmt: - n, ok := n.(*ast.IfStmt) - return ok && n.Else != nil && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) && - m.matchNamed(state, m.stringValue(inst), m.toStmtSlice(state, n.Cond, n.Init)) - - case opCaseClause: - n, ok := n.(*ast.CaseClause) - return ok && n.List != nil && m.matchExprSlice(state, n.List) && m.matchStmtSlice(state, n.Body) - case opDefaultCaseClause: - n, ok := n.(*ast.CaseClause) - return ok && n.List == nil && m.matchStmtSlice(state, n.Body) - - case opSwitchStmt: - n, ok := n.(*ast.SwitchStmt) - return ok && n.Init == nil && n.Tag == nil && m.matchStmtSlice(state, n.Body.List) - case opSwitchTagStmt: - n, ok := n.(*ast.SwitchStmt) - return ok && n.Init == nil && m.matchNode(state, n.Tag) && m.matchStmtSlice(state, n.Body.List) - case opSwitchInitStmt: - n, ok := n.(*ast.SwitchStmt) - return ok && n.Tag == nil && m.matchNode(state, n.Init) && m.matchStmtSlice(state, n.Body.List) - case opSwitchInitTagStmt: - n, ok := n.(*ast.SwitchStmt) - return ok && m.matchNode(state, n.Init) && m.matchNode(state, n.Tag) && m.matchStmtSlice(state, n.Body.List) - - case opTypeSwitchStmt: - n, ok := n.(*ast.TypeSwitchStmt) - return ok && n.Init == nil && m.matchNode(state, n.Assign) && m.matchStmtSlice(state, n.Body.List) - case opTypeSwitchInitStmt: - n, ok := n.(*ast.TypeSwitchStmt) - return ok && m.matchNode(state, n.Init) && - m.matchNode(state, n.Assign) && m.matchStmtSlice(state, n.Body.List) - - case opCommClause: - n, ok := n.(*ast.CommClause) - return ok && n.Comm != nil && m.matchNode(state, n.Comm) && m.matchStmtSlice(state, n.Body) - case opDefaultCommClause: - n, ok := n.(*ast.CommClause) - return ok && n.Comm == nil && m.matchStmtSlice(state, n.Body) - - case opSelectStmt: - n, ok := n.(*ast.SelectStmt) - return ok && m.matchStmtSlice(state, n.Body.List) - - case opRangeStmt: - n, ok := n.(*ast.RangeStmt) - return ok && n.Key == nil && n.Value == nil && m.matchNode(state, n.X) && m.matchNode(state, n.Body) - case opRangeKeyStmt: - n, ok := n.(*ast.RangeStmt) - return ok && n.Key != nil && n.Value == nil && token.Token(inst.value) == n.Tok && - m.matchNode(state, n.Key) && m.matchNode(state, n.X) && m.matchNode(state, n.Body) - case opRangeKeyValueStmt: - n, ok := n.(*ast.RangeStmt) - return ok && n.Key != nil && n.Value != nil && token.Token(inst.value) == n.Tok && - m.matchNode(state, n.Key) && m.matchNode(state, n.Value) && m.matchNode(state, n.X) && m.matchNode(state, n.Body) - - case opForStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init == nil && n.Cond == nil && n.Post == nil && - m.matchNode(state, n.Body) - case opForPostStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init == nil && n.Cond == nil && n.Post != nil && - m.matchNode(state, n.Post) && m.matchNode(state, n.Body) - case opForCondStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init == nil && n.Cond != nil && n.Post == nil && - m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) - case opForCondPostStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init == nil && n.Cond != nil && n.Post != nil && - m.matchNode(state, n.Cond) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) - case opForInitStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init != nil && n.Cond == nil && n.Post == nil && - m.matchNode(state, n.Init) && m.matchNode(state, n.Body) - case opForInitPostStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init != nil && n.Cond == nil && n.Post != nil && - m.matchNode(state, n.Init) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) - case opForInitCondStmt: - n, ok := n.(*ast.ForStmt) - return ok && n.Init != nil && n.Cond != nil && n.Post == nil && - m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) - case opForInitCondPostStmt: - n, ok := n.(*ast.ForStmt) - return ok && m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) - - case opIncDecStmt: - n, ok := n.(*ast.IncDecStmt) - return ok && token.Token(inst.value) == n.Tok && m.matchNode(state, n.X) - - case opReturnStmt: - n, ok := n.(*ast.ReturnStmt) - return ok && m.matchExprSlice(state, n.Results) - - case opLabeledStmt: - n, ok := n.(*ast.LabeledStmt) - return ok && m.matchNode(state, n.Label) && m.matchNode(state, n.Stmt) - case opSimpleLabeledStmt: - n, ok := n.(*ast.LabeledStmt) - return ok && m.stringValue(inst) == n.Label.Name && m.matchNode(state, n.Stmt) - - case opLabeledBranchStmt: - n, ok := n.(*ast.BranchStmt) - return ok && n.Label != nil && token.Token(inst.value) == n.Tok && m.matchNode(state, n.Label) - case opSimpleLabeledBranchStmt: - n, ok := n.(*ast.BranchStmt) - return ok && n.Label != nil && m.stringValue(inst) == n.Label.Name && token.Token(inst.value) == n.Tok - case opBranchStmt: - n, ok := n.(*ast.BranchStmt) - return ok && n.Label == nil && token.Token(inst.value) == n.Tok - - case opEmptyStmt: - _, ok := n.(*ast.EmptyStmt) - return ok - - case opSimpleFuncDecl: - n, ok := n.(*ast.FuncDecl) - return ok && n.Recv == nil && n.Body != nil && typeparams.ForFuncType(n.Type) == nil && - n.Name.Name == m.stringValue(inst) && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) - case opFuncDecl: - n, ok := n.(*ast.FuncDecl) - return ok && n.Recv == nil && n.Body != nil && - m.matchNode(state, n.Name) && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) - case opFuncProtoDecl: - n, ok := n.(*ast.FuncDecl) - return ok && n.Recv == nil && n.Body == nil && typeparams.ForFuncType(n.Type) == nil && - m.matchNode(state, n.Name) && m.matchNode(state, n.Type) - case opMethodDecl: - n, ok := n.(*ast.FuncDecl) - return ok && n.Recv != nil && n.Body != nil && - m.matchNode(state, n.Recv) && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) - case opMethodProtoDecl: - n, ok := n.(*ast.FuncDecl) - return ok && n.Recv != nil && n.Body == nil && - m.matchNode(state, n.Recv) && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) - - case opValueSpec: - n, ok := n.(*ast.ValueSpec) - return ok && len(n.Values) == 0 && n.Type == nil && - len(n.Names) == 1 && m.matchNode(state, n.Names[0]) - case opValueInitSpec: - n, ok := n.(*ast.ValueSpec) - return ok && len(n.Values) != 0 && n.Type == nil && - m.matchIdentSlice(state, n.Names) && m.matchExprSlice(state, n.Values) - case opTypedValueSpec: - n, ok := n.(*ast.ValueSpec) - return ok && len(n.Values) == 0 && n.Type != nil && - m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) - case opTypedValueInitSpec: - n, ok := n.(*ast.ValueSpec) - return ok && len(n.Values) != 0 && - m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) && m.matchExprSlice(state, n.Values) - - case opSimpleTypeSpec: - n, ok := n.(*ast.TypeSpec) - return ok && !n.Assign.IsValid() && typeparams.ForTypeSpec(n) == nil && n.Name.Name == m.stringValue(inst) && m.matchNode(state, n.Type) - case opTypeSpec: - n, ok := n.(*ast.TypeSpec) - return ok && !n.Assign.IsValid() && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) - case opGenericTypeSpec: - n, ok := n.(*ast.TypeSpec) - return ok && !n.Assign.IsValid() && m.matchNode(state, n.Name) && m.matchNode(state, typeparams.ForTypeSpec(n)) && m.matchNode(state, n.Type) - case opTypeAliasSpec: - n, ok := n.(*ast.TypeSpec) - return ok && n.Assign.IsValid() && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) - - case opDeclStmt: - n, ok := n.(*ast.DeclStmt) - return ok && m.matchNode(state, n.Decl) - - case opConstDecl: - n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.CONST && m.matchSpecSlice(state, n.Specs) - case opVarDecl: - n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.VAR && m.matchSpecSlice(state, n.Specs) - case opTypeDecl: - n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.TYPE && m.matchSpecSlice(state, n.Specs) - case opAnyImportDecl: - n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.IMPORT - case opImportDecl: - n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.IMPORT && m.matchSpecSlice(state, n.Specs) - - case opEmptyPackage: - n, ok := n.(*ast.File) - return ok && len(n.Imports) == 0 && len(n.Decls) == 0 && m.matchNode(state, n.Name) - - default: - panic(fmt.Sprintf("unexpected op %s", inst.op)) - } -} - -func (m *matcher) matchNode(state *MatcherState, n ast.Node) bool { - return m.matchNodeWithInst(state, m.nextInst(state), n) -} - -func (m *matcher) matchArgList(state *MatcherState, exprs []ast.Expr) bool { - inst := m.nextInst(state) - if inst.op != opSimpleArgList { - return m.matchExprSlice(state, exprs) - } - if len(exprs) != int(inst.value) { - return false - } - for _, x := range exprs { - if !m.matchNode(state, x) { - return false - } - } - return true -} - -func (m *matcher) matchStmtSlice(state *MatcherState, stmts []ast.Stmt) bool { - slice := m.allocNodeSlice(state) - slice.assignStmtSlice(stmts) - matched, _ := m.matchNodeList(state, slice, false) - return matched != nil -} - -func (m *matcher) matchExprSlice(state *MatcherState, exprs []ast.Expr) bool { - slice := m.allocNodeSlice(state) - slice.assignExprSlice(exprs) - matched, _ := m.matchNodeList(state, slice, false) - return matched != nil -} - -func (m *matcher) matchFieldSlice(state *MatcherState, fields []*ast.Field) bool { - slice := m.allocNodeSlice(state) - slice.assignFieldSlice(fields) - matched, _ := m.matchNodeList(state, slice, false) - return matched != nil -} - -func (m *matcher) matchIdentSlice(state *MatcherState, idents []*ast.Ident) bool { - slice := m.allocNodeSlice(state) - slice.assignIdentSlice(idents) - matched, _ := m.matchNodeList(state, slice, false) - return matched != nil -} - -func (m *matcher) matchSpecSlice(state *MatcherState, specs []ast.Spec) bool { - slice := m.allocNodeSlice(state) - slice.assignSpecSlice(specs) - matched, _ := m.matchNodeList(state, slice, false) - return matched != nil -} - -// matchNodeList matches two lists of nodes. It uses a common algorithm to match -// wildcard patterns with any number of nodes without recursion. -func (m *matcher) matchNodeList(state *MatcherState, nodes *NodeSlice, partial bool) (matched ast.Node, offset int) { - sliceLen := nodes.Len() - inst := m.nextInst(state) - if inst.op == opEnd { - if sliceLen == 0 { - return nodes, 0 - } - return nil, -1 - } - pcBase := state.pc - pcNext := 0 - j := 0 - jNext := 0 - partialStart, partialEnd := 0, sliceLen - - type restart struct { - matches []CapturedNode - pc int - j int - wildStart int - wildName string - } - // We need to stack these because otherwise some edge cases - // would not match properly. Since we have various kinds of - // wildcards (nodes containing them, $_, and $*_), in some cases - // we may have to go back and do multiple restarts to get to the - // right starting position. - var stack []restart - wildName := "" - wildStart := 0 - push := func(next int) { - if next > sliceLen { - return // would be discarded anyway - } - pcNext = state.pc - 1 - jNext = next - stack = append(stack, restart{state.capture, pcNext, next, wildStart, wildName}) - } - pop := func() { - j = jNext - state.pc = pcNext - state.capture = stack[len(stack)-1].matches - wildName = stack[len(stack)-1].wildName - wildStart = stack[len(stack)-1].wildStart - stack = stack[:len(stack)-1] - pcNext = 0 - jNext = 0 - if len(stack) != 0 { - pcNext = stack[len(stack)-1].pc - jNext = stack[len(stack)-1].j - } - } - - // wouldMatch returns whether the current wildcard - if any - - // matches the nodes we are currently trying it on. - wouldMatch := func() bool { - switch wildName { - case "", "_": - return true - } - slice := m.allocNodeSlice(state) - nodes.SliceInto(slice, wildStart, j) - return m.matchNamed(state, wildName, slice) - } - for ; inst.op != opEnd || j < sliceLen; inst = m.nextInst(state) { - if inst.op != opEnd { - if inst.op == opNodeSeq || inst.op == opNamedNodeSeq { - // keep track of where this wildcard - // started (if name == wildName, - // we're trying the same wildcard - // matching one more node) - name := "_" - if inst.op == opNamedNodeSeq { - name = m.stringValue(inst) - } - if name != wildName { - wildStart = j - wildName = name - } - // try to match zero or more at j, - // restarting at j+1 if it fails - push(j + 1) - continue - } - if partial && state.pc == pcBase { - // let "b; c" match "a; b; c" - // (simulates a $*_ at the beginning) - partialStart = j - push(j + 1) - } - if j < sliceLen && wouldMatch() && m.matchNodeWithInst(state, inst, nodes.At(j)) { - // ordinary match - wildName = "" - j++ - continue - } - } - if partial && inst.op == opEnd && wildName == "" { - partialEnd = j - break // let "b; c" match "b; c; d" - } - // mismatch, try to restart - if 0 < jNext && jNext <= sliceLen && (state.pc != pcNext || j != jNext) { - pop() - continue - } - return nil, -1 - } - if !wouldMatch() { - return nil, -1 - } - slice := m.allocNodeSlice(state) - nodes.SliceInto(slice, partialStart, partialEnd) - return slice, partialEnd + 1 -} - -func (m *matcher) matchRangeClause(state *MatcherState, n ast.Node, accept func(MatchData)) { - rng, ok := n.(*ast.RangeStmt) - if !ok { - return - } - m.resetCapture(state) - if !m.matchNode(state, rng.X) { - return - } - - // Now the fun begins: there is no Range pos in RangeStmt, so we need - // to make our best guess to find it. - // See https://github.com/golang/go/issues/50429 - // - // In gogrep we don't have []byte sources available, and - // it would be cumbersome to walk bytes manually to find the "range" keyword. - // What we can do is to hope that code is: - // 1. Properly gofmt-ed. - // 2. There are no some freefloating artifacts between TokPos and "range". - var from int - if rng.TokPos != token.NoPos { - // Start from the end of the '=' or ':=' token. - from = int(rng.TokPos + 1) - if rng.Tok == token.DEFINE { - from++ // ':=' is 1 byte longer that '=' - } - // Now suppose we have 'for _, x := range xs {...}' - // If this is true, then `xs.Pos.Offset - len(" range ")` would - // lead us to the current 'from' value. - // It's syntactically correct to have `:=range`, so we don't - // unconditionally add a space here. - if int(rng.X.Pos())-len(" range ") == from { - // This means that there is exactly one space between Tok and "range". - // There are some afwul cases where this might break, but let's - // not think about them too much. - from += len(" ") - } - } else { - // `for range xs {...}` form. - // There should be at least 1 space between "for" and "range". - from = int(rng.For) + len("for ") - } - - state.partial.X = rng - state.partial.from = token.Pos(from) - state.partial.to = rng.X.End() - - accept(MatchData{ - Capture: state.capture, - Node: &state.partial, - }) -} - -func (m *matcher) matchRangeHeader(state *MatcherState, n ast.Node, accept func(MatchData)) { - rng, ok := n.(*ast.RangeStmt) - if ok && rng.Key == nil && rng.Value == nil && m.matchNode(state, rng.X) { - m.setRangeHeaderPos(state, rng) - accept(MatchData{ - Capture: state.capture, - Node: &state.partial, - }) - } -} - -func (m *matcher) matchRangeKeyHeader(state *MatcherState, inst instruction, n ast.Node, accept func(MatchData)) { - rng, ok := n.(*ast.RangeStmt) - if ok && rng.Key != nil && rng.Value == nil && token.Token(inst.value) == rng.Tok && m.matchNode(state, rng.Key) && m.matchNode(state, rng.X) { - m.setRangeHeaderPos(state, rng) - accept(MatchData{ - Capture: state.capture, - Node: &state.partial, - }) - } -} - -func (m *matcher) matchRangeKeyValueHeader(state *MatcherState, inst instruction, n ast.Node, accept func(MatchData)) { - rng, ok := n.(*ast.RangeStmt) - if ok && rng.Key != nil && rng.Value != nil && token.Token(inst.value) == rng.Tok && m.matchNode(state, rng.Key) && m.matchNode(state, rng.Value) && m.matchNode(state, rng.X) { - m.setRangeHeaderPos(state, rng) - accept(MatchData{ - Capture: state.capture, - Node: &state.partial, - }) - } -} - -func (m *matcher) setRangeHeaderPos(state *MatcherState, rng *ast.RangeStmt) { - state.partial.X = rng - state.partial.from = rng.Pos() - state.partial.to = rng.Body.Pos() - 1 -} - -func findNamed(capture []CapturedNode, name string) (ast.Node, bool) { - for _, c := range capture { - if c.Name == name { - return c.Node, true - } - } - return nil, false -} - -func literalValue(lit *ast.BasicLit) interface{} { - switch lit.Kind { - case token.INT: - v, err := strconv.ParseInt(lit.Value, 0, 64) - if err == nil { - return v - } - case token.CHAR: - s, err := strconv.Unquote(lit.Value) - if err != nil { - return nil - } - // Return the first rune. - for _, c := range s { - return c - } - case token.STRING: - s, err := strconv.Unquote(lit.Value) - if err == nil { - return s - } - case token.FLOAT: - v, err := strconv.ParseFloat(lit.Value, 64) - if err == nil { - return v - } - case token.IMAG: - v, err := strconv.ParseComplex(lit.Value, 128) - if err == nil { - return v - } - } - return nil -} - -func equalNodes(x, y ast.Node) bool { - if x == nil || y == nil { - return x == y - } - if x, ok := x.(*NodeSlice); ok { - y, ok := y.(*NodeSlice) - if !ok || x.Kind != y.Kind || x.Len() != y.Len() { - return false - } - switch x.Kind { - case ExprNodeSlice: - for i, n1 := range x.exprSlice { - n2 := y.exprSlice[i] - if !astequal.Expr(n1, n2) { - return false - } - } - case StmtNodeSlice: - for i, n1 := range x.stmtSlice { - n2 := y.stmtSlice[i] - if !astequal.Stmt(n1, n2) { - return false - } - } - case FieldNodeSlice: - for i, n1 := range x.fieldSlice { - n2 := y.fieldSlice[i] - if !astequal.Node(n1, n2) { - return false - } - } - case IdentNodeSlice: - for i, n1 := range x.identSlice { - n2 := y.identSlice[i] - if n1.Name != n2.Name { - return false - } - } - case SpecNodeSlice: - for i, n1 := range x.specSlice { - n2 := y.specSlice[i] - if !astequal.Node(n1, n2) { - return false - } - } - case DeclNodeSlice: - for i, n1 := range x.declSlice { - n2 := y.declSlice[i] - if !astequal.Decl(n1, n2) { - return false - } - } - } - return true - } - return astequal.Node(x, y) -} diff --git a/vendor/github.com/quasilyte/gogrep/nodetag/nodetag.go b/vendor/github.com/quasilyte/gogrep/nodetag/nodetag.go deleted file mode 100644 index 8060e0ece..000000000 --- a/vendor/github.com/quasilyte/gogrep/nodetag/nodetag.go +++ /dev/null @@ -1,287 +0,0 @@ -package nodetag - -import ( - "go/ast" - - "golang.org/x/exp/typeparams" -) - -type Value int - -const ( - Unknown Value = iota - - ArrayType - AssignStmt - BasicLit - BinaryExpr - BlockStmt - BranchStmt - CallExpr - CaseClause - ChanType - CommClause - CompositeLit - DeclStmt - DeferStmt - Ellipsis - EmptyStmt - ExprStmt - File - ForStmt - FuncDecl - FuncLit - FuncType - GenDecl - GoStmt - Ident - IfStmt - ImportSpec - IncDecStmt - IndexExpr - IndexListExpr - InterfaceType - KeyValueExpr - LabeledStmt - MapType - ParenExpr - RangeStmt - ReturnStmt - SelectStmt - SelectorExpr - SendStmt - SliceExpr - StarExpr - StructType - SwitchStmt - TypeAssertExpr - TypeSpec - TypeSwitchStmt - UnaryExpr - ValueSpec - - NumBuckets - - StmtList // gogrep stmt list - ExprList // gogrep expr list - DeclList // gogrep decl list - - Node // ast.Node - Expr // ast.Expr - Stmt // ast.Stmt -) - -func FromNode(n ast.Node) Value { - switch n.(type) { - case *ast.ArrayType: - return ArrayType - case *ast.AssignStmt: - return AssignStmt - case *ast.BasicLit: - return BasicLit - case *ast.BinaryExpr: - return BinaryExpr - case *ast.BlockStmt: - return BlockStmt - case *ast.BranchStmt: - return BranchStmt - case *ast.CallExpr: - return CallExpr - case *ast.CaseClause: - return CaseClause - case *ast.ChanType: - return ChanType - case *ast.CommClause: - return CommClause - case *ast.CompositeLit: - return CompositeLit - case *ast.DeclStmt: - return DeclStmt - case *ast.DeferStmt: - return DeferStmt - case *ast.Ellipsis: - return Ellipsis - case *ast.EmptyStmt: - return EmptyStmt - case *ast.ExprStmt: - return ExprStmt - case *ast.File: - return File - case *ast.ForStmt: - return ForStmt - case *ast.FuncDecl: - return FuncDecl - case *ast.FuncLit: - return FuncLit - case *ast.FuncType: - return FuncType - case *ast.GenDecl: - return GenDecl - case *ast.GoStmt: - return GoStmt - case *ast.Ident: - return Ident - case *ast.IfStmt: - return IfStmt - case *ast.ImportSpec: - return ImportSpec - case *ast.IncDecStmt: - return IncDecStmt - case *ast.IndexExpr: - return IndexExpr - case *typeparams.IndexListExpr: - return IndexListExpr - case *ast.InterfaceType: - return InterfaceType - case *ast.KeyValueExpr: - return KeyValueExpr - case *ast.LabeledStmt: - return LabeledStmt - case *ast.MapType: - return MapType - case *ast.ParenExpr: - return ParenExpr - case *ast.RangeStmt: - return RangeStmt - case *ast.ReturnStmt: - return ReturnStmt - case *ast.SelectStmt: - return SelectStmt - case *ast.SelectorExpr: - return SelectorExpr - case *ast.SendStmt: - return SendStmt - case *ast.SliceExpr: - return SliceExpr - case *ast.StarExpr: - return StarExpr - case *ast.StructType: - return StructType - case *ast.SwitchStmt: - return SwitchStmt - case *ast.TypeAssertExpr: - return TypeAssertExpr - case *ast.TypeSpec: - return TypeSpec - case *ast.TypeSwitchStmt: - return TypeSwitchStmt - case *ast.UnaryExpr: - return UnaryExpr - case *ast.ValueSpec: - return ValueSpec - default: - return Unknown - } -} - -func FromString(s string) Value { - switch s { - case "Expr": - return Expr - case "Stmt": - return Stmt - case "Node": - return Node - } - - switch s { - case "ArrayType": - return ArrayType - case "AssignStmt": - return AssignStmt - case "BasicLit": - return BasicLit - case "BinaryExpr": - return BinaryExpr - case "BlockStmt": - return BlockStmt - case "BranchStmt": - return BranchStmt - case "CallExpr": - return CallExpr - case "CaseClause": - return CaseClause - case "ChanType": - return ChanType - case "CommClause": - return CommClause - case "CompositeLit": - return CompositeLit - case "DeclStmt": - return DeclStmt - case "DeferStmt": - return DeferStmt - case "Ellipsis": - return Ellipsis - case "EmptyStmt": - return EmptyStmt - case "ExprStmt": - return ExprStmt - case "File": - return File - case "ForStmt": - return ForStmt - case "FuncDecl": - return FuncDecl - case "FuncLit": - return FuncLit - case "FuncType": - return FuncType - case "GenDecl": - return GenDecl - case "GoStmt": - return GoStmt - case "Ident": - return Ident - case "IfStmt": - return IfStmt - case "ImportSpec": - return ImportSpec - case "IncDecStmt": - return IncDecStmt - case "IndexExpr": - return IndexExpr - case "IndexListExpr": - return IndexListExpr - case "InterfaceType": - return InterfaceType - case "KeyValueExpr": - return KeyValueExpr - case "LabeledStmt": - return LabeledStmt - case "MapType": - return MapType - case "ParenExpr": - return ParenExpr - case "RangeStmt": - return RangeStmt - case "ReturnStmt": - return ReturnStmt - case "SelectStmt": - return SelectStmt - case "SelectorExpr": - return SelectorExpr - case "SendStmt": - return SendStmt - case "SliceExpr": - return SliceExpr - case "StarExpr": - return StarExpr - case "StructType": - return StructType - case "SwitchStmt": - return SwitchStmt - case "TypeAssertExpr": - return TypeAssertExpr - case "TypeSpec": - return TypeSpec - case "TypeSwitchStmt": - return TypeSwitchStmt - case "UnaryExpr": - return UnaryExpr - case "ValueSpec": - return ValueSpec - default: - return Unknown - } -} diff --git a/vendor/github.com/quasilyte/gogrep/operation_string.go b/vendor/github.com/quasilyte/gogrep/operation_string.go deleted file mode 100644 index 23eb20062..000000000 --- a/vendor/github.com/quasilyte/gogrep/operation_string.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by "stringer -type=operation -trimprefix=op"; DO NOT EDIT. - -package gogrep - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[opInvalid-0] - _ = x[opNode-1] - _ = x[opNamedNode-2] - _ = x[opNodeSeq-3] - _ = x[opNamedNodeSeq-4] - _ = x[opOptNode-5] - _ = x[opNamedOptNode-6] - _ = x[opFieldNode-7] - _ = x[opNamedFieldNode-8] - _ = x[opMultiStmt-9] - _ = x[opMultiExpr-10] - _ = x[opMultiDecl-11] - _ = x[opEnd-12] - _ = x[opBasicLit-13] - _ = x[opStrictIntLit-14] - _ = x[opStrictFloatLit-15] - _ = x[opStrictCharLit-16] - _ = x[opStrictStringLit-17] - _ = x[opStrictComplexLit-18] - _ = x[opIdent-19] - _ = x[opPkg-20] - _ = x[opIndexExpr-21] - _ = x[opIndexListExpr-22] - _ = x[opSliceExpr-23] - _ = x[opSliceFromExpr-24] - _ = x[opSliceToExpr-25] - _ = x[opSliceFromToExpr-26] - _ = x[opSliceToCapExpr-27] - _ = x[opSliceFromToCapExpr-28] - _ = x[opFuncLit-29] - _ = x[opCompositeLit-30] - _ = x[opTypedCompositeLit-31] - _ = x[opSimpleSelectorExpr-32] - _ = x[opSelectorExpr-33] - _ = x[opTypeAssertExpr-34] - _ = x[opTypeSwitchAssertExpr-35] - _ = x[opStructType-36] - _ = x[opInterfaceType-37] - _ = x[opEfaceType-38] - _ = x[opVoidFuncType-39] - _ = x[opGenericVoidFuncType-40] - _ = x[opFuncType-41] - _ = x[opGenericFuncType-42] - _ = x[opArrayType-43] - _ = x[opSliceType-44] - _ = x[opMapType-45] - _ = x[opChanType-46] - _ = x[opKeyValueExpr-47] - _ = x[opEllipsis-48] - _ = x[opTypedEllipsis-49] - _ = x[opStarExpr-50] - _ = x[opUnaryExpr-51] - _ = x[opBinaryExpr-52] - _ = x[opParenExpr-53] - _ = x[opArgList-54] - _ = x[opSimpleArgList-55] - _ = x[opVariadicCallExpr-56] - _ = x[opNonVariadicCallExpr-57] - _ = x[opMaybeVariadicCallExpr-58] - _ = x[opCallExpr-59] - _ = x[opAssignStmt-60] - _ = x[opMultiAssignStmt-61] - _ = x[opBranchStmt-62] - _ = x[opSimpleLabeledBranchStmt-63] - _ = x[opLabeledBranchStmt-64] - _ = x[opSimpleLabeledStmt-65] - _ = x[opLabeledStmt-66] - _ = x[opBlockStmt-67] - _ = x[opExprStmt-68] - _ = x[opGoStmt-69] - _ = x[opDeferStmt-70] - _ = x[opSendStmt-71] - _ = x[opEmptyStmt-72] - _ = x[opIncDecStmt-73] - _ = x[opReturnStmt-74] - _ = x[opIfStmt-75] - _ = x[opIfInitStmt-76] - _ = x[opIfElseStmt-77] - _ = x[opIfInitElseStmt-78] - _ = x[opIfNamedOptStmt-79] - _ = x[opIfNamedOptElseStmt-80] - _ = x[opSwitchStmt-81] - _ = x[opSwitchTagStmt-82] - _ = x[opSwitchInitStmt-83] - _ = x[opSwitchInitTagStmt-84] - _ = x[opSelectStmt-85] - _ = x[opTypeSwitchStmt-86] - _ = x[opTypeSwitchInitStmt-87] - _ = x[opCaseClause-88] - _ = x[opDefaultCaseClause-89] - _ = x[opCommClause-90] - _ = x[opDefaultCommClause-91] - _ = x[opForStmt-92] - _ = x[opForPostStmt-93] - _ = x[opForCondStmt-94] - _ = x[opForCondPostStmt-95] - _ = x[opForInitStmt-96] - _ = x[opForInitPostStmt-97] - _ = x[opForInitCondStmt-98] - _ = x[opForInitCondPostStmt-99] - _ = x[opRangeStmt-100] - _ = x[opRangeKeyStmt-101] - _ = x[opRangeKeyValueStmt-102] - _ = x[opRangeClause-103] - _ = x[opRangeHeader-104] - _ = x[opRangeKeyHeader-105] - _ = x[opRangeKeyValueHeader-106] - _ = x[opFieldList-107] - _ = x[opUnnamedField-108] - _ = x[opSimpleField-109] - _ = x[opField-110] - _ = x[opMultiField-111] - _ = x[opValueSpec-112] - _ = x[opValueInitSpec-113] - _ = x[opTypedValueInitSpec-114] - _ = x[opTypedValueSpec-115] - _ = x[opSimpleTypeSpec-116] - _ = x[opTypeSpec-117] - _ = x[opGenericTypeSpec-118] - _ = x[opTypeAliasSpec-119] - _ = x[opSimpleFuncDecl-120] - _ = x[opFuncDecl-121] - _ = x[opMethodDecl-122] - _ = x[opFuncProtoDecl-123] - _ = x[opMethodProtoDecl-124] - _ = x[opDeclStmt-125] - _ = x[opConstDecl-126] - _ = x[opVarDecl-127] - _ = x[opTypeDecl-128] - _ = x[opAnyImportDecl-129] - _ = x[opImportDecl-130] - _ = x[opEmptyPackage-131] -} - -const _operation_name = "InvalidNodeNamedNodeNodeSeqNamedNodeSeqOptNodeNamedOptNodeFieldNodeNamedFieldNodeMultiStmtMultiExprMultiDeclEndBasicLitStrictIntLitStrictFloatLitStrictCharLitStrictStringLitStrictComplexLitIdentPkgIndexExprIndexListExprSliceExprSliceFromExprSliceToExprSliceFromToExprSliceToCapExprSliceFromToCapExprFuncLitCompositeLitTypedCompositeLitSimpleSelectorExprSelectorExprTypeAssertExprTypeSwitchAssertExprStructTypeInterfaceTypeEfaceTypeVoidFuncTypeGenericVoidFuncTypeFuncTypeGenericFuncTypeArrayTypeSliceTypeMapTypeChanTypeKeyValueExprEllipsisTypedEllipsisStarExprUnaryExprBinaryExprParenExprArgListSimpleArgListVariadicCallExprNonVariadicCallExprMaybeVariadicCallExprCallExprAssignStmtMultiAssignStmtBranchStmtSimpleLabeledBranchStmtLabeledBranchStmtSimpleLabeledStmtLabeledStmtBlockStmtExprStmtGoStmtDeferStmtSendStmtEmptyStmtIncDecStmtReturnStmtIfStmtIfInitStmtIfElseStmtIfInitElseStmtIfNamedOptStmtIfNamedOptElseStmtSwitchStmtSwitchTagStmtSwitchInitStmtSwitchInitTagStmtSelectStmtTypeSwitchStmtTypeSwitchInitStmtCaseClauseDefaultCaseClauseCommClauseDefaultCommClauseForStmtForPostStmtForCondStmtForCondPostStmtForInitStmtForInitPostStmtForInitCondStmtForInitCondPostStmtRangeStmtRangeKeyStmtRangeKeyValueStmtRangeClauseRangeHeaderRangeKeyHeaderRangeKeyValueHeaderFieldListUnnamedFieldSimpleFieldFieldMultiFieldValueSpecValueInitSpecTypedValueInitSpecTypedValueSpecSimpleTypeSpecTypeSpecGenericTypeSpecTypeAliasSpecSimpleFuncDeclFuncDeclMethodDeclFuncProtoDeclMethodProtoDeclDeclStmtConstDeclVarDeclTypeDeclAnyImportDeclImportDeclEmptyPackage" - -var _operation_index = [...]uint16{0, 7, 11, 20, 27, 39, 46, 58, 67, 81, 90, 99, 108, 111, 119, 131, 145, 158, 173, 189, 194, 197, 206, 219, 228, 241, 252, 267, 281, 299, 306, 318, 335, 353, 365, 379, 399, 409, 422, 431, 443, 462, 470, 485, 494, 503, 510, 518, 530, 538, 551, 559, 568, 578, 587, 594, 607, 623, 642, 663, 671, 681, 696, 706, 729, 746, 763, 774, 783, 791, 797, 806, 814, 823, 833, 843, 849, 859, 869, 883, 897, 915, 925, 938, 952, 969, 979, 993, 1011, 1021, 1038, 1048, 1065, 1072, 1083, 1094, 1109, 1120, 1135, 1150, 1169, 1178, 1190, 1207, 1218, 1229, 1243, 1262, 1271, 1283, 1294, 1299, 1309, 1318, 1331, 1349, 1363, 1377, 1385, 1400, 1413, 1427, 1435, 1445, 1458, 1473, 1481, 1490, 1497, 1505, 1518, 1528, 1540} - -func (i operation) String() string { - if i >= operation(len(_operation_index)-1) { - return "operation(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _operation_name[_operation_index[i]:_operation_index[i+1]] -} diff --git a/vendor/github.com/quasilyte/gogrep/operations.gen.go b/vendor/github.com/quasilyte/gogrep/operations.gen.go deleted file mode 100644 index 9af838ab8..000000000 --- a/vendor/github.com/quasilyte/gogrep/operations.gen.go +++ /dev/null @@ -1,1671 +0,0 @@ -// Code generated "gen_operations.go"; DO NOT EDIT. - -package gogrep - -import ( - "github.com/quasilyte/gogrep/nodetag" -) - -//go:generate stringer -type=operation -trimprefix=op -type operation uint8 - -const ( - opInvalid operation = 0 - - // Tag: Node - opNode operation = 1 - - // Tag: Node - // ValueIndex: strings | wildcard name - opNamedNode operation = 2 - - // Tag: Unknown - opNodeSeq operation = 3 - - // Tag: Unknown - // ValueIndex: strings | wildcard name - opNamedNodeSeq operation = 4 - - // Tag: Unknown - opOptNode operation = 5 - - // Tag: Unknown - // ValueIndex: strings | wildcard name - opNamedOptNode operation = 6 - - // Tag: Node - opFieldNode operation = 7 - - // Tag: Node - // ValueIndex: strings | wildcard name - opNamedFieldNode operation = 8 - - // Tag: StmtList - // Args: stmts... - // Example: f(); g() - opMultiStmt operation = 9 - - // Tag: ExprList - // Args: exprs... - // Example: f(), g() - opMultiExpr operation = 10 - - // Tag: DeclList - // Args: exprs... - // Example: f(), g() - opMultiDecl operation = 11 - - // Tag: Unknown - opEnd operation = 12 - - // Tag: BasicLit - // ValueIndex: ifaces | parsed literal value - opBasicLit operation = 13 - - // Tag: BasicLit - // ValueIndex: strings | raw literal value - opStrictIntLit operation = 14 - - // Tag: BasicLit - // ValueIndex: strings | raw literal value - opStrictFloatLit operation = 15 - - // Tag: BasicLit - // ValueIndex: strings | raw literal value - opStrictCharLit operation = 16 - - // Tag: BasicLit - // ValueIndex: strings | raw literal value - opStrictStringLit operation = 17 - - // Tag: BasicLit - // ValueIndex: strings | raw literal value - opStrictComplexLit operation = 18 - - // Tag: Ident - // ValueIndex: strings | ident name - opIdent operation = 19 - - // Tag: Ident - // ValueIndex: strings | package path - opPkg operation = 20 - - // Tag: IndexExpr - // Args: x expr - opIndexExpr operation = 21 - - // Tag: IndexListExpr - // Args: x exprs... - opIndexListExpr operation = 22 - - // Tag: SliceExpr - // Args: x - opSliceExpr operation = 23 - - // Tag: SliceExpr - // Args: x from - // Example: x[from:] - opSliceFromExpr operation = 24 - - // Tag: SliceExpr - // Args: x to - // Example: x[:to] - opSliceToExpr operation = 25 - - // Tag: SliceExpr - // Args: x from to - // Example: x[from:to] - opSliceFromToExpr operation = 26 - - // Tag: SliceExpr - // Args: x from cap - // Example: x[:from:cap] - opSliceToCapExpr operation = 27 - - // Tag: SliceExpr - // Args: x from to cap - // Example: x[from:to:cap] - opSliceFromToCapExpr operation = 28 - - // Tag: FuncLit - // Args: type block - opFuncLit operation = 29 - - // Tag: CompositeLit - // Args: elts... - // Example: {elts...} - opCompositeLit operation = 30 - - // Tag: CompositeLit - // Args: typ elts... - // Example: typ{elts...} - opTypedCompositeLit operation = 31 - - // Tag: SelectorExpr - // Args: x - // ValueIndex: strings | selector name - opSimpleSelectorExpr operation = 32 - - // Tag: SelectorExpr - // Args: x sel - opSelectorExpr operation = 33 - - // Tag: TypeAssertExpr - // Args: x typ - opTypeAssertExpr operation = 34 - - // Tag: TypeAssertExpr - // Args: x - opTypeSwitchAssertExpr operation = 35 - - // Tag: StructType - // Args: fields - opStructType operation = 36 - - // Tag: InterfaceType - // Args: fields - opInterfaceType operation = 37 - - // Tag: InterfaceType - opEfaceType operation = 38 - - // Tag: FuncType - // Args: params - opVoidFuncType operation = 39 - - // Tag: FuncType - // Args: typeparams params - opGenericVoidFuncType operation = 40 - - // Tag: FuncType - // Args: params results - opFuncType operation = 41 - - // Tag: FuncType - // Args: typeparams params results - opGenericFuncType operation = 42 - - // Tag: ArrayType - // Args: length elem - opArrayType operation = 43 - - // Tag: ArrayType - // Args: elem - opSliceType operation = 44 - - // Tag: MapType - // Args: key value - opMapType operation = 45 - - // Tag: ChanType - // Args: value - // Value: ast.ChanDir | channel direction - opChanType operation = 46 - - // Tag: KeyValueExpr - // Args: key value - opKeyValueExpr operation = 47 - - // Tag: Ellipsis - opEllipsis operation = 48 - - // Tag: Ellipsis - // Args: type - opTypedEllipsis operation = 49 - - // Tag: StarExpr - // Args: x - opStarExpr operation = 50 - - // Tag: UnaryExpr - // Args: x - // Value: token.Token | unary operator - opUnaryExpr operation = 51 - - // Tag: BinaryExpr - // Args: x y - // Value: token.Token | binary operator - opBinaryExpr operation = 52 - - // Tag: ParenExpr - // Args: x - opParenExpr operation = 53 - - // Tag: Unknown - // Args: exprs... - // Example: 1, 2, 3 - opArgList operation = 54 - - // Tag: Unknown - // Like ArgList, but pattern contains no $* - // Args: exprs[] - // Example: 1, 2, 3 - // Value: int | slice len - opSimpleArgList operation = 55 - - // Tag: CallExpr - // Args: fn args - // Example: f(1, xs...) - opVariadicCallExpr operation = 56 - - // Tag: CallExpr - // Args: fn args - // Example: f(1, xs) - opNonVariadicCallExpr operation = 57 - - // Tag: CallExpr - // Args: fn args - // Example: f(1, xs) or f(1, xs...) - // Value: int | can be variadic if len(args)>value - opMaybeVariadicCallExpr operation = 58 - - // Tag: CallExpr - // Args: fn args - // Example: f(1, xs) or f(1, xs...) - opCallExpr operation = 59 - - // Tag: AssignStmt - // Args: lhs rhs - // Example: lhs := rhs() - // Value: token.Token | ':=' or '=' - opAssignStmt operation = 60 - - // Tag: AssignStmt - // Args: lhs... rhs... - // Example: lhs1, lhs2 := rhs() - // Value: token.Token | ':=' or '=' - opMultiAssignStmt operation = 61 - - // Tag: BranchStmt - // Args: x - // Value: token.Token | branch kind - opBranchStmt operation = 62 - - // Tag: BranchStmt - // Args: x - // Value: token.Token | branch kind - // ValueIndex: strings | label name - opSimpleLabeledBranchStmt operation = 63 - - // Tag: BranchStmt - // Args: label x - // Value: token.Token | branch kind - opLabeledBranchStmt operation = 64 - - // Tag: LabeledStmt - // Args: x - // ValueIndex: strings | label name - opSimpleLabeledStmt operation = 65 - - // Tag: LabeledStmt - // Args: label x - opLabeledStmt operation = 66 - - // Tag: BlockStmt - // Args: body... - opBlockStmt operation = 67 - - // Tag: ExprStmt - // Args: x - opExprStmt operation = 68 - - // Tag: GoStmt - // Args: x - opGoStmt operation = 69 - - // Tag: DeferStmt - // Args: x - opDeferStmt operation = 70 - - // Tag: SendStmt - // Args: ch value - opSendStmt operation = 71 - - // Tag: EmptyStmt - opEmptyStmt operation = 72 - - // Tag: IncDecStmt - // Args: x - // Value: token.Token | '++' or '--' - opIncDecStmt operation = 73 - - // Tag: ReturnStmt - // Args: results... - opReturnStmt operation = 74 - - // Tag: IfStmt - // Args: cond block - // Example: if cond {} - opIfStmt operation = 75 - - // Tag: IfStmt - // Args: init cond block - // Example: if init; cond {} - opIfInitStmt operation = 76 - - // Tag: IfStmt - // Args: cond block else - // Example: if cond {} else ... - opIfElseStmt operation = 77 - - // Tag: IfStmt - // Args: init cond block else - // Example: if init; cond {} else ... - opIfInitElseStmt operation = 78 - - // Tag: IfStmt - // Args: block - // Example: if $*x {} - // ValueIndex: strings | wildcard name - opIfNamedOptStmt operation = 79 - - // Tag: IfStmt - // Args: block else - // Example: if $*x {} else ... - // ValueIndex: strings | wildcard name - opIfNamedOptElseStmt operation = 80 - - // Tag: SwitchStmt - // Args: body... - // Example: switch {} - opSwitchStmt operation = 81 - - // Tag: SwitchStmt - // Args: tag body... - // Example: switch tag {} - opSwitchTagStmt operation = 82 - - // Tag: SwitchStmt - // Args: init body... - // Example: switch init; {} - opSwitchInitStmt operation = 83 - - // Tag: SwitchStmt - // Args: init tag body... - // Example: switch init; tag {} - opSwitchInitTagStmt operation = 84 - - // Tag: SelectStmt - // Args: body... - opSelectStmt operation = 85 - - // Tag: TypeSwitchStmt - // Args: x block - // Example: switch x.(type) {} - opTypeSwitchStmt operation = 86 - - // Tag: TypeSwitchStmt - // Args: init x block - // Example: switch init; x.(type) {} - opTypeSwitchInitStmt operation = 87 - - // Tag: CaseClause - // Args: values... body... - opCaseClause operation = 88 - - // Tag: CaseClause - // Args: body... - opDefaultCaseClause operation = 89 - - // Tag: CommClause - // Args: comm body... - opCommClause operation = 90 - - // Tag: CommClause - // Args: body... - opDefaultCommClause operation = 91 - - // Tag: ForStmt - // Args: blocl - // Example: for {} - opForStmt operation = 92 - - // Tag: ForStmt - // Args: post block - // Example: for ; ; post {} - opForPostStmt operation = 93 - - // Tag: ForStmt - // Args: cond block - // Example: for ; cond; {} - opForCondStmt operation = 94 - - // Tag: ForStmt - // Args: cond post block - // Example: for ; cond; post {} - opForCondPostStmt operation = 95 - - // Tag: ForStmt - // Args: init block - // Example: for init; ; {} - opForInitStmt operation = 96 - - // Tag: ForStmt - // Args: init post block - // Example: for init; ; post {} - opForInitPostStmt operation = 97 - - // Tag: ForStmt - // Args: init cond block - // Example: for init; cond; {} - opForInitCondStmt operation = 98 - - // Tag: ForStmt - // Args: init cond post block - // Example: for init; cond; post {} - opForInitCondPostStmt operation = 99 - - // Tag: RangeStmt - // Args: x block - // Example: for range x {} - opRangeStmt operation = 100 - - // Tag: RangeStmt - // Args: key x block - // Example: for key := range x {} - // Value: token.Token | ':=' or '=' - opRangeKeyStmt operation = 101 - - // Tag: RangeStmt - // Args: key value x block - // Example: for key, value := range x {} - // Value: token.Token | ':=' or '=' - opRangeKeyValueStmt operation = 102 - - // Tag: RangeStmt - // Args: x - // Example: range x - opRangeClause operation = 103 - - // Tag: RangeStmt - // Args: x - // Example: for range x - opRangeHeader operation = 104 - - // Tag: RangeStmt - // Args: key x - // Example: for key := range x - // Value: token.Token | ':=' or '=' - opRangeKeyHeader operation = 105 - - // Tag: RangeStmt - // Args: key value x - // Example: for key, value := range x - // Value: token.Token | ':=' or '=' - opRangeKeyValueHeader operation = 106 - - // Tag: Unknown - // Args: fields... - opFieldList operation = 107 - - // Tag: Unknown - // Args: typ - // Example: type - opUnnamedField operation = 108 - - // Tag: Unknown - // Args: typ - // Example: name type - // ValueIndex: strings | field name - opSimpleField operation = 109 - - // Tag: Unknown - // Args: name typ - // Example: $name type - opField operation = 110 - - // Tag: Unknown - // Args: names... typ - // Example: name1, name2 type - opMultiField operation = 111 - - // Tag: ValueSpec - // Args: value - opValueSpec operation = 112 - - // Tag: ValueSpec - // Args: lhs... rhs... - // Example: lhs = rhs - opValueInitSpec operation = 113 - - // Tag: ValueSpec - // Args: lhs... type rhs... - // Example: lhs typ = rhs - opTypedValueInitSpec operation = 114 - - // Tag: ValueSpec - // Args: lhs... type - // Example: lhs typ - opTypedValueSpec operation = 115 - - // Tag: TypeSpec - // Args: type - // Example: name type - // ValueIndex: strings | type name - opSimpleTypeSpec operation = 116 - - // Tag: TypeSpec - // Args: name type - // Example: name type - opTypeSpec operation = 117 - - // Tag: TypeSpec - // Args: name typeparasm type - // Example: name[typeparams] type - opGenericTypeSpec operation = 118 - - // Tag: TypeSpec - // Args: name type - // Example: name = type - opTypeAliasSpec operation = 119 - - // Tag: FuncDecl - // Args: type block - // ValueIndex: strings | field name - opSimpleFuncDecl operation = 120 - - // Tag: FuncDecl - // Args: name type block - opFuncDecl operation = 121 - - // Tag: FuncDecl - // Args: recv name type block - opMethodDecl operation = 122 - - // Tag: FuncDecl - // Args: name type - opFuncProtoDecl operation = 123 - - // Tag: FuncDecl - // Args: recv name type - opMethodProtoDecl operation = 124 - - // Tag: DeclStmt - // Args: decl - opDeclStmt operation = 125 - - // Tag: GenDecl - // Args: valuespecs... - opConstDecl operation = 126 - - // Tag: GenDecl - // Args: valuespecs... - opVarDecl operation = 127 - - // Tag: GenDecl - // Args: typespecs... - opTypeDecl operation = 128 - - // Tag: GenDecl - opAnyImportDecl operation = 129 - - // Tag: GenDecl - // Args: importspecs... - opImportDecl operation = 130 - - // Tag: File - // Args: name - opEmptyPackage operation = 131 -) - -type operationInfo struct { - Tag nodetag.Value - NumArgs int - ValueKind valueKind - ExtraValueKind valueKind - VariadicMap bitmap64 - SliceIndex int -} - -var operationInfoTable = [256]operationInfo{ - opInvalid: {}, - - opNode: { - Tag: nodetag.Node, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNamedNode: { - Tag: nodetag.Node, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNodeSeq: { - Tag: nodetag.Unknown, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNamedNodeSeq: { - Tag: nodetag.Unknown, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opOptNode: { - Tag: nodetag.Unknown, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNamedOptNode: { - Tag: nodetag.Unknown, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFieldNode: { - Tag: nodetag.Node, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNamedFieldNode: { - Tag: nodetag.Node, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMultiStmt: { - Tag: nodetag.StmtList, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opMultiExpr: { - Tag: nodetag.ExprList, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opMultiDecl: { - Tag: nodetag.DeclList, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opEnd: { - Tag: nodetag.Unknown, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opBasicLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: ifaceValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStrictIntLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStrictFloatLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStrictCharLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStrictStringLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStrictComplexLit: { - Tag: nodetag.BasicLit, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIdent: { - Tag: nodetag.Ident, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opPkg: { - Tag: nodetag.Ident, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIndexExpr: { - Tag: nodetag.IndexExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIndexListExpr: { - Tag: nodetag.IndexListExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 - SliceIndex: -1, - }, - opSliceExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceFromExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceToExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceFromToExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceToCapExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceFromToCapExpr: { - Tag: nodetag.SliceExpr, - NumArgs: 4, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFuncLit: { - Tag: nodetag.FuncLit, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opCompositeLit: { - Tag: nodetag.CompositeLit, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opTypedCompositeLit: { - Tag: nodetag.CompositeLit, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 - SliceIndex: -1, - }, - opSimpleSelectorExpr: { - Tag: nodetag.SelectorExpr, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSelectorExpr: { - Tag: nodetag.SelectorExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypeAssertExpr: { - Tag: nodetag.TypeAssertExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypeSwitchAssertExpr: { - Tag: nodetag.TypeAssertExpr, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStructType: { - Tag: nodetag.StructType, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opInterfaceType: { - Tag: nodetag.InterfaceType, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opEfaceType: { - Tag: nodetag.InterfaceType, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opVoidFuncType: { - Tag: nodetag.FuncType, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opGenericVoidFuncType: { - Tag: nodetag.FuncType, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFuncType: { - Tag: nodetag.FuncType, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opGenericFuncType: { - Tag: nodetag.FuncType, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opArrayType: { - Tag: nodetag.ArrayType, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSliceType: { - Tag: nodetag.ArrayType, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMapType: { - Tag: nodetag.MapType, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opChanType: { - Tag: nodetag.ChanType, - NumArgs: 1, - ValueKind: chandirValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opKeyValueExpr: { - Tag: nodetag.KeyValueExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opEllipsis: { - Tag: nodetag.Ellipsis, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypedEllipsis: { - Tag: nodetag.Ellipsis, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opStarExpr: { - Tag: nodetag.StarExpr, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opUnaryExpr: { - Tag: nodetag.UnaryExpr, - NumArgs: 1, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opBinaryExpr: { - Tag: nodetag.BinaryExpr, - NumArgs: 2, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opParenExpr: { - Tag: nodetag.ParenExpr, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opArgList: { - Tag: nodetag.Unknown, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opSimpleArgList: { - Tag: nodetag.Unknown, - NumArgs: 1, - ValueKind: intValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: 0, - }, - opVariadicCallExpr: { - Tag: nodetag.CallExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opNonVariadicCallExpr: { - Tag: nodetag.CallExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMaybeVariadicCallExpr: { - Tag: nodetag.CallExpr, - NumArgs: 2, - ValueKind: intValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opCallExpr: { - Tag: nodetag.CallExpr, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opAssignStmt: { - Tag: nodetag.AssignStmt, - NumArgs: 2, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMultiAssignStmt: { - Tag: nodetag.AssignStmt, - NumArgs: 2, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 3, // 11 - SliceIndex: -1, - }, - opBranchStmt: { - Tag: nodetag.BranchStmt, - NumArgs: 1, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSimpleLabeledBranchStmt: { - Tag: nodetag.BranchStmt, - NumArgs: 1, - ValueKind: tokenValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opLabeledBranchStmt: { - Tag: nodetag.BranchStmt, - NumArgs: 2, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSimpleLabeledStmt: { - Tag: nodetag.LabeledStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opLabeledStmt: { - Tag: nodetag.LabeledStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opBlockStmt: { - Tag: nodetag.BlockStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opExprStmt: { - Tag: nodetag.ExprStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opGoStmt: { - Tag: nodetag.GoStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opDeferStmt: { - Tag: nodetag.DeferStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSendStmt: { - Tag: nodetag.SendStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opEmptyStmt: { - Tag: nodetag.EmptyStmt, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIncDecStmt: { - Tag: nodetag.IncDecStmt, - NumArgs: 1, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opReturnStmt: { - Tag: nodetag.ReturnStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opIfStmt: { - Tag: nodetag.IfStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIfInitStmt: { - Tag: nodetag.IfStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIfElseStmt: { - Tag: nodetag.IfStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIfInitElseStmt: { - Tag: nodetag.IfStmt, - NumArgs: 4, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIfNamedOptStmt: { - Tag: nodetag.IfStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opIfNamedOptElseStmt: { - Tag: nodetag.IfStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSwitchStmt: { - Tag: nodetag.SwitchStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opSwitchTagStmt: { - Tag: nodetag.SwitchStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 - SliceIndex: -1, - }, - opSwitchInitStmt: { - Tag: nodetag.SwitchStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 - SliceIndex: -1, - }, - opSwitchInitTagStmt: { - Tag: nodetag.SwitchStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 4, // 100 - SliceIndex: -1, - }, - opSelectStmt: { - Tag: nodetag.SelectStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opTypeSwitchStmt: { - Tag: nodetag.TypeSwitchStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypeSwitchInitStmt: { - Tag: nodetag.TypeSwitchStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opCaseClause: { - Tag: nodetag.CaseClause, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 3, // 11 - SliceIndex: -1, - }, - opDefaultCaseClause: { - Tag: nodetag.CaseClause, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opCommClause: { - Tag: nodetag.CommClause, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 - SliceIndex: -1, - }, - opDefaultCommClause: { - Tag: nodetag.CommClause, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opForStmt: { - Tag: nodetag.ForStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForPostStmt: { - Tag: nodetag.ForStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForCondStmt: { - Tag: nodetag.ForStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForCondPostStmt: { - Tag: nodetag.ForStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForInitStmt: { - Tag: nodetag.ForStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForInitPostStmt: { - Tag: nodetag.ForStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForInitCondStmt: { - Tag: nodetag.ForStmt, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opForInitCondPostStmt: { - Tag: nodetag.ForStmt, - NumArgs: 4, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeStmt: { - Tag: nodetag.RangeStmt, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeKeyStmt: { - Tag: nodetag.RangeStmt, - NumArgs: 3, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeKeyValueStmt: { - Tag: nodetag.RangeStmt, - NumArgs: 4, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeClause: { - Tag: nodetag.RangeStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeHeader: { - Tag: nodetag.RangeStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeKeyHeader: { - Tag: nodetag.RangeStmt, - NumArgs: 2, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opRangeKeyValueHeader: { - Tag: nodetag.RangeStmt, - NumArgs: 3, - ValueKind: tokenValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFieldList: { - Tag: nodetag.Unknown, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opUnnamedField: { - Tag: nodetag.Unknown, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSimpleField: { - Tag: nodetag.Unknown, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opField: { - Tag: nodetag.Unknown, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMultiField: { - Tag: nodetag.Unknown, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opValueSpec: { - Tag: nodetag.ValueSpec, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opValueInitSpec: { - Tag: nodetag.ValueSpec, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 3, // 11 - SliceIndex: -1, - }, - opTypedValueInitSpec: { - Tag: nodetag.ValueSpec, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 5, // 101 - SliceIndex: -1, - }, - opTypedValueSpec: { - Tag: nodetag.ValueSpec, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opSimpleTypeSpec: { - Tag: nodetag.TypeSpec, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypeSpec: { - Tag: nodetag.TypeSpec, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opGenericTypeSpec: { - Tag: nodetag.TypeSpec, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opTypeAliasSpec: { - Tag: nodetag.TypeSpec, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opSimpleFuncDecl: { - Tag: nodetag.FuncDecl, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: stringValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFuncDecl: { - Tag: nodetag.FuncDecl, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMethodDecl: { - Tag: nodetag.FuncDecl, - NumArgs: 4, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opFuncProtoDecl: { - Tag: nodetag.FuncDecl, - NumArgs: 2, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opMethodProtoDecl: { - Tag: nodetag.FuncDecl, - NumArgs: 3, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opDeclStmt: { - Tag: nodetag.DeclStmt, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opConstDecl: { - Tag: nodetag.GenDecl, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opVarDecl: { - Tag: nodetag.GenDecl, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opTypeDecl: { - Tag: nodetag.GenDecl, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opAnyImportDecl: { - Tag: nodetag.GenDecl, - NumArgs: 0, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, - opImportDecl: { - Tag: nodetag.GenDecl, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 1, // 1 - SliceIndex: -1, - }, - opEmptyPackage: { - Tag: nodetag.File, - NumArgs: 1, - ValueKind: emptyValue, - ExtraValueKind: emptyValue, - VariadicMap: 0, // 0 - SliceIndex: -1, - }, -} diff --git a/vendor/github.com/quasilyte/gogrep/parse.go b/vendor/github.com/quasilyte/gogrep/parse.go deleted file mode 100644 index 3c6854bda..000000000 --- a/vendor/github.com/quasilyte/gogrep/parse.go +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2017, Daniel Martí -// See LICENSE for licensing information - -package gogrep - -import ( - "bytes" - "fmt" - "go/ast" - "go/parser" - "go/scanner" - "go/token" - "strings" - "text/template" -) - -func transformSource(expr string) (string, []posOffset, error) { - toks, err := tokenize([]byte(expr)) - if err != nil { - return "", nil, fmt.Errorf("cannot tokenize expr: %v", err) - } - var offs []posOffset - lbuf := lineColBuffer{line: 1, col: 1} - lastLit := false - for _, t := range toks { - if lbuf.offs >= t.pos.Offset && lastLit && t.lit != "" { - _, _ = lbuf.WriteString(" ") - } - for lbuf.offs < t.pos.Offset { - _, _ = lbuf.WriteString(" ") - } - if t.lit == "" { - _, _ = lbuf.WriteString(t.tok.String()) - lastLit = false - continue - } - _, _ = lbuf.WriteString(t.lit) - lastLit = strings.TrimSpace(t.lit) != "" - } - // trailing newlines can cause issues with commas - return strings.TrimSpace(lbuf.String()), offs, nil -} - -func parseExpr(fset *token.FileSet, expr string) (ast.Node, error) { - exprStr, offs, err := transformSource(expr) - if err != nil { - return nil, err - } - node, err := parseDetectingNode(fset, exprStr) - if err != nil { - err = subPosOffsets(err, offs...) - return nil, fmt.Errorf("cannot parse expr: %v", err) - } - return node, nil -} - -type lineColBuffer struct { - bytes.Buffer - line, col, offs int -} - -func (l *lineColBuffer) WriteString(s string) (n int, err error) { - for _, r := range s { - if r == '\n' { - l.line++ - l.col = 1 - } else { - l.col++ - } - l.offs++ - } - return l.Buffer.WriteString(s) -} - -var tmplDecl = template.Must(template.New("").Parse(`` + - `package p; {{ . }}`)) - -var tmplBlock = template.Must(template.New("").Parse(`` + - `package p; func _() { if true {{ . }} else {} }`)) - -var tmplExprs = template.Must(template.New("").Parse(`` + - `package p; var _ = []interface{}{ {{ . }}, }`)) - -var tmplStmts = template.Must(template.New("").Parse(`` + - `package p; func _() { {{ . }} }`)) - -var tmplType = template.Must(template.New("").Parse(`` + - `package p; var _ {{ . }}`)) - -var tmplValSpec = template.Must(template.New("").Parse(`` + - `package p; var {{ . }}`)) - -func execTmpl(tmpl *template.Template, src string) string { - var buf bytes.Buffer - if err := tmpl.Execute(&buf, src); err != nil { - panic(err) - } - return buf.String() -} - -func noBadNodes(node ast.Node) bool { - any := false - ast.Inspect(node, func(n ast.Node) bool { - if any { - return false - } - switch n.(type) { - case *ast.BadExpr, *ast.BadDecl: - any = true - } - return true - }) - return !any -} - -func parseType(fset *token.FileSet, src string) (ast.Expr, *ast.File, error) { - asType := execTmpl(tmplType, src) - f, err := parser.ParseFile(fset, "", asType, 0) - if err != nil { - err = subPosOffsets(err, posOffset{1, 1, 17}) - return nil, nil, err - } - vs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec) - return vs.Type, f, nil -} - -// parseDetectingNode tries its best to parse the ast.Node contained in src, as -// one of: *ast.File, ast.Decl, ast.Expr, ast.Stmt, *ast.ValueSpec. -// It also returns the *ast.File used for the parsing, so that the returned node -// can be easily type-checked. -func parseDetectingNode(fset *token.FileSet, src string) (ast.Node, error) { - file := fset.AddFile("", fset.Base(), len(src)) - scan := scanner.Scanner{} - scan.Init(file, []byte(src), nil, 0) - if _, tok, _ := scan.Scan(); tok == token.EOF { - return nil, fmt.Errorf("empty source code") - } - var mainErr error - - // Some adhoc patterns first. - if strings.HasPrefix(src, "range ") { - e, err := parser.ParseExpr(src[len("range "):]) - if err == nil && noBadNodes(e) { - return &rangeClause{X: e}, nil - } - } - if strings.HasPrefix(src, "for ") && !strings.HasSuffix(src, "}") { - asStmts := execTmpl(tmplStmts, src+"{}") - f, err := parser.ParseFile(fset, "", asStmts, parser.SkipObjectResolution) - if err == nil && noBadNodes(f) { - bl := f.Decls[0].(*ast.FuncDecl).Body - if len(bl.List) == 1 { - return &rangeHeader{Node: bl.List[0].(*ast.RangeStmt)}, nil - } - } - } - - // try as a block; otherwise blocks might be mistaken for composite - // literals further below\ - asBlock := execTmpl(tmplBlock, src) - if f, err := parser.ParseFile(fset, "", asBlock, parser.SkipObjectResolution); err == nil && noBadNodes(f) { - bl := f.Decls[0].(*ast.FuncDecl).Body - if len(bl.List) == 1 { - ifs := bl.List[0].(*ast.IfStmt) - return ifs.Body, nil - } - } - - // then as value expressions - asExprs := execTmpl(tmplExprs, src) - if f, err := parser.ParseFile(fset, "", asExprs, parser.SkipObjectResolution); err == nil && noBadNodes(f) { - vs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec) - cl := vs.Values[0].(*ast.CompositeLit) - if len(cl.Elts) == 1 { - return cl.Elts[0], nil - } - slice := &NodeSlice{} - slice.assignExprSlice(cl.Elts) - return slice, nil - } - - // then try as statements - asStmts := execTmpl(tmplStmts, src) - f, err := parser.ParseFile(fset, "", asStmts, parser.SkipObjectResolution) - if err == nil && noBadNodes(f) { - bl := f.Decls[0].(*ast.FuncDecl).Body - if len(bl.List) == 1 { - return bl.List[0], nil - } - slice := &NodeSlice{} - slice.assignStmtSlice(bl.List) - return slice, nil - } - // Statements is what covers most cases, so it will give - // the best overall error message. Show positions - // relative to where the user's code is put in the - // template. - mainErr = subPosOffsets(err, posOffset{1, 1, 22}) - - // try as a single declaration, or many - asDecl := execTmpl(tmplDecl, src) - if f, err := parser.ParseFile(fset, "", asDecl, 0); err == nil && noBadNodes(f) { - if len(f.Decls) == 1 { - return f.Decls[0], nil - } - slice := &NodeSlice{} - slice.assignDeclSlice(f.Decls) - return slice, nil - } - - // try as a whole file - if f, err := parser.ParseFile(fset, "", src, 0); err == nil && noBadNodes(f) { - return f, nil - } - - // type expressions not yet picked up, for e.g. chans and interfaces - if typ, f, err := parseType(fset, src); err == nil && noBadNodes(f) { - return typ, nil - } - - // value specs - asValSpec := execTmpl(tmplValSpec, src) - if f, err := parser.ParseFile(fset, "", asValSpec, 0); err == nil && noBadNodes(f) { - decl := f.Decls[0].(*ast.GenDecl) - if len(decl.Specs) != 0 { - vs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec) - return vs, nil - } - } - - return nil, mainErr -} - -type posOffset struct { - atLine, atCol int - offset int -} - -func subPosOffsets(err error, offs ...posOffset) error { - list, ok := err.(scanner.ErrorList) - if !ok { - return err - } - for i, err := range list { - for _, off := range offs { - if err.Pos.Line != off.atLine { - continue - } - if err.Pos.Column < off.atCol { - continue - } - err.Pos.Column -= off.offset - } - list[i] = err - } - return list -} - -type fullToken struct { - pos token.Position - tok token.Token - lit string -} - -type caseStatus uint - -const ( - caseNone caseStatus = iota - caseNeedBlock - caseHere -) - -func tokenize(src []byte) ([]fullToken, error) { - var s scanner.Scanner - fset := token.NewFileSet() - file := fset.AddFile("", fset.Base(), len(src)) - - var err error - onError := func(pos token.Position, msg string) { - switch msg { // allow certain extra chars - case `illegal character U+0024 '$'`: - case `illegal character U+007E '~'`: - default: - err = fmt.Errorf("%v: %s", pos, msg) - } - } - - // we will modify the input source under the scanner's nose to - // enable some features such as regexes. - s.Init(file, src, onError, scanner.ScanComments) - - next := func() fullToken { - pos, tok, lit := s.Scan() - return fullToken{fset.Position(pos), tok, lit} - } - - caseStat := caseNone - - var toks []fullToken - for t := next(); t.tok != token.EOF; t = next() { - switch t.lit { - case "$": // continues below - case "switch", "select", "case": - if t.lit == "case" { - caseStat = caseNone - } else { - caseStat = caseNeedBlock - } - fallthrough - default: // regular Go code - if t.tok == token.LBRACE && caseStat == caseNeedBlock { - caseStat = caseHere - } - toks = append(toks, t) - continue - } - wt, err := tokenizeWildcard(t.pos, next) - if err != nil { - return nil, err - } - if caseStat == caseHere { - toks = append(toks, fullToken{wt.pos, token.IDENT, "case"}) - } - toks = append(toks, wt) - if caseStat == caseHere { - toks = append(toks, - fullToken{wt.pos, token.COLON, ""}, - fullToken{wt.pos, token.IDENT, "gogrep_body"}) - } - } - return toks, err -} - -type varInfo struct { - Name string - Seq bool -} - -func tokenizeWildcard(pos token.Position, next func() fullToken) (fullToken, error) { - t := next() - any := false - if t.tok == token.MUL { - t = next() - any = true - } - wildName := encodeWildName(t.lit, any) - wt := fullToken{pos, token.IDENT, wildName} - if t.tok != token.IDENT { - return wt, fmt.Errorf("%v: $ must be followed by ident, got %v", - t.pos, t.tok) - } - return wt, nil -} - -const wildSeparator = "ᐸᐳ" - -func isWildName(s string) bool { - return strings.HasPrefix(s, wildSeparator) -} - -func encodeWildName(name string, any bool) string { - suffix := "v" - if any { - suffix = "a" - } - return wildSeparator + name + wildSeparator + suffix -} - -func decodeWildName(s string) varInfo { - s = s[len(wildSeparator):] - nameEnd := strings.Index(s, wildSeparator) - name := s[:nameEnd+0] - s = s[nameEnd:] - s = s[len(wildSeparator):] - kind := s - return varInfo{Name: name, Seq: kind == "a"} -} - -func decodeWildNode(n ast.Node) varInfo { - switch n := n.(type) { - case *ast.ExprStmt: - return decodeWildNode(n.X) - case *ast.Ident: - if isWildName(n.Name) { - return decodeWildName(n.Name) - } - } - return varInfo{} -} - -type rangeClause struct { - X ast.Expr -} - -type rangeHeader struct { - Node *ast.RangeStmt -} - -func (*rangeClause) Pos() token.Pos { return 0 } -func (*rangeClause) End() token.Pos { return 0 } - -func (*rangeHeader) Pos() token.Pos { return 0 } -func (*rangeHeader) End() token.Pos { return 0 } diff --git a/vendor/github.com/quasilyte/gogrep/slices.go b/vendor/github.com/quasilyte/gogrep/slices.go deleted file mode 100644 index fb969b51b..000000000 --- a/vendor/github.com/quasilyte/gogrep/slices.go +++ /dev/null @@ -1,150 +0,0 @@ -package gogrep - -import ( - "go/ast" - "go/token" -) - -type NodeSliceKind uint32 - -const ( - ExprNodeSlice NodeSliceKind = iota - StmtNodeSlice - FieldNodeSlice - IdentNodeSlice - SpecNodeSlice - DeclNodeSlice -) - -type NodeSlice struct { - Kind NodeSliceKind - - exprSlice []ast.Expr - stmtSlice []ast.Stmt - fieldSlice []*ast.Field - identSlice []*ast.Ident - specSlice []ast.Spec - declSlice []ast.Decl -} - -func (s *NodeSlice) GetExprSlice() []ast.Expr { return s.exprSlice } -func (s *NodeSlice) GetStmtSlice() []ast.Stmt { return s.stmtSlice } -func (s *NodeSlice) GetFieldSlice() []*ast.Field { return s.fieldSlice } -func (s *NodeSlice) GetIdentSlice() []*ast.Ident { return s.identSlice } -func (s *NodeSlice) GetSpecSlice() []ast.Spec { return s.specSlice } -func (s *NodeSlice) GetDeclSlice() []ast.Decl { return s.declSlice } - -func (s *NodeSlice) assignExprSlice(xs []ast.Expr) { - s.Kind = ExprNodeSlice - s.exprSlice = xs -} - -func (s *NodeSlice) assignStmtSlice(xs []ast.Stmt) { - s.Kind = StmtNodeSlice - s.stmtSlice = xs -} - -func (s *NodeSlice) assignFieldSlice(xs []*ast.Field) { - s.Kind = FieldNodeSlice - s.fieldSlice = xs -} - -func (s *NodeSlice) assignIdentSlice(xs []*ast.Ident) { - s.Kind = IdentNodeSlice - s.identSlice = xs -} - -func (s *NodeSlice) assignSpecSlice(xs []ast.Spec) { - s.Kind = SpecNodeSlice - s.specSlice = xs -} - -func (s *NodeSlice) assignDeclSlice(xs []ast.Decl) { - s.Kind = DeclNodeSlice - s.declSlice = xs -} - -func (s *NodeSlice) Len() int { - switch s.Kind { - case ExprNodeSlice: - return len(s.exprSlice) - case StmtNodeSlice: - return len(s.stmtSlice) - case FieldNodeSlice: - return len(s.fieldSlice) - case IdentNodeSlice: - return len(s.identSlice) - case SpecNodeSlice: - return len(s.specSlice) - default: - return len(s.declSlice) - } -} - -func (s *NodeSlice) At(i int) ast.Node { - switch s.Kind { - case ExprNodeSlice: - return s.exprSlice[i] - case StmtNodeSlice: - return s.stmtSlice[i] - case FieldNodeSlice: - return s.fieldSlice[i] - case IdentNodeSlice: - return s.identSlice[i] - case SpecNodeSlice: - return s.specSlice[i] - default: - return s.declSlice[i] - } -} - -func (s *NodeSlice) SliceInto(dst *NodeSlice, i, j int) { - switch s.Kind { - case ExprNodeSlice: - dst.assignExprSlice(s.exprSlice[i:j]) - case StmtNodeSlice: - dst.assignStmtSlice(s.stmtSlice[i:j]) - case FieldNodeSlice: - dst.assignFieldSlice(s.fieldSlice[i:j]) - case IdentNodeSlice: - dst.assignIdentSlice(s.identSlice[i:j]) - case SpecNodeSlice: - dst.assignSpecSlice(s.specSlice[i:j]) - default: - dst.assignDeclSlice(s.declSlice[i:j]) - } -} - -func (s *NodeSlice) Pos() token.Pos { - switch s.Kind { - case ExprNodeSlice: - return s.exprSlice[0].Pos() - case StmtNodeSlice: - return s.stmtSlice[0].Pos() - case FieldNodeSlice: - return s.fieldSlice[0].Pos() - case IdentNodeSlice: - return s.identSlice[0].Pos() - case SpecNodeSlice: - return s.specSlice[0].Pos() - default: - return s.declSlice[0].Pos() - } -} - -func (s *NodeSlice) End() token.Pos { - switch s.Kind { - case ExprNodeSlice: - return s.exprSlice[len(s.exprSlice)-1].End() - case StmtNodeSlice: - return s.stmtSlice[len(s.stmtSlice)-1].End() - case FieldNodeSlice: - return s.fieldSlice[len(s.fieldSlice)-1].End() - case IdentNodeSlice: - return s.identSlice[len(s.identSlice)-1].End() - case SpecNodeSlice: - return s.specSlice[len(s.specSlice)-1].End() - default: - return s.declSlice[len(s.declSlice)-1].End() - } -} diff --git a/vendor/github.com/quasilyte/regex/syntax/LICENSE b/vendor/github.com/quasilyte/regex/syntax/LICENSE deleted file mode 100644 index f0c81282b..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Iskander (Alex) Sharipov / quasilyte - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/quasilyte/regex/syntax/README.md b/vendor/github.com/quasilyte/regex/syntax/README.md deleted file mode 100644 index b70e25ad9..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Package `regex/syntax` - -Package `syntax` provides regular expressions parser as well as AST definitions. - -## Rationale - -The advantages of this package over stdlib [regexp/syntax](https://golang.org/pkg/regexp/syntax/): - -1. Does not transformations/optimizations during the parsing. - The produced parse tree is loseless. - -2. Simpler AST representation. - -3. Can parse most PCRE operations in addition to [re2](https://github.com/google/re2/wiki/Syntax) syntax. - It can also handle PHP/Perl style patterns with delimiters. - -4. This package is easier to extend than something from the standard library. - -This package does almost no assumptions about how generated AST is going to be used -so it preserves as much syntax information as possible. - -It's easy to write another intermediate representation on top of it. The main -function of this package is to convert a textual regexp pattern into a more -structured form that can be processed more easily. - -## Users - -* [go-critic](https://github.com/go-critic/go-critic) - Go static analyzer -* [NoVerify](https://github.com/VKCOM/noverify) - PHP static analyzer diff --git a/vendor/github.com/quasilyte/regex/syntax/ast.go b/vendor/github.com/quasilyte/regex/syntax/ast.go deleted file mode 100644 index 4d21a9432..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/ast.go +++ /dev/null @@ -1,64 +0,0 @@ -package syntax - -import ( - "strings" -) - -type Regexp struct { - Pattern string - Expr Expr -} - -type RegexpPCRE struct { - Pattern string - Expr Expr - - Source string - Modifiers string - Delim [2]byte -} - -func (re *RegexpPCRE) HasModifier(mod byte) bool { - return strings.IndexByte(re.Modifiers, mod) >= 0 -} - -type Expr struct { - // The operations that this expression performs. See `operation.go`. - Op Operation - - Form Form - - _ [2]byte // Reserved - - // Pos describes a source location inside regexp pattern. - Pos Position - - // Args is a list of sub-expressions of this expression. - // - // See Operation constants documentation to learn how to - // interpret the particular expression args. - Args []Expr - - // Value holds expression textual value. - // - // Usually, that value is identical to src[Begin():End()], - // but this is not true for programmatically generated objects. - Value string -} - -// Begin returns expression leftmost offset. -func (e Expr) Begin() uint16 { return e.Pos.Begin } - -// End returns expression rightmost offset. -func (e Expr) End() uint16 { return e.Pos.End } - -// LastArg returns expression last argument. -// -// Should not be called on expressions that may have 0 arguments. -func (e Expr) LastArg() Expr { - return e.Args[len(e.Args)-1] -} - -type Operation byte - -type Form byte diff --git a/vendor/github.com/quasilyte/regex/syntax/errors.go b/vendor/github.com/quasilyte/regex/syntax/errors.go deleted file mode 100644 index beefba5f9..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/errors.go +++ /dev/null @@ -1,27 +0,0 @@ -package syntax - -type ParseError struct { - Pos Position - Message string -} - -func (e ParseError) Error() string { return e.Message } - -func throw(pos Position, message string) { - panic(ParseError{Pos: pos, Message: message}) -} - -func throwExpectedFound(pos Position, expected, found string) { - throw(pos, "expected '"+expected+"', found '"+found+"'") -} - -func throwUnexpectedToken(pos Position, token string) { - throw(pos, "unexpected token: "+token) -} - -func newPos(begin, end int) Position { - return Position{ - Begin: uint16(begin), - End: uint16(end), - } -} diff --git a/vendor/github.com/quasilyte/regex/syntax/lexer.go b/vendor/github.com/quasilyte/regex/syntax/lexer.go deleted file mode 100644 index aae146c2e..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/lexer.go +++ /dev/null @@ -1,454 +0,0 @@ -package syntax - -import ( - "strings" - "unicode/utf8" -) - -type token struct { - kind tokenKind - pos Position -} - -func (tok token) String() string { - return tok.kind.String() -} - -type tokenKind byte - -//go:generate stringer -type=tokenKind -trimprefix=tok -linecomment=true -const ( - tokNone tokenKind = iota - - tokChar - tokGroupFlags - tokPosixClass - tokConcat - tokRepeat - tokEscapeChar - tokEscapeMeta - tokEscapeOctal - tokEscapeUni - tokEscapeUniFull - tokEscapeHex - tokEscapeHexFull - tokComment - - tokQ // \Q - tokMinus // - - tokLbracket // [ - tokLbracketCaret // [^ - tokRbracket // ] - tokDollar // $ - tokCaret // ^ - tokQuestion // ? - tokDot // . - tokPlus // + - tokStar // * - tokPipe // | - tokLparen // ( - tokLparenName // (?P - tokLparenNameAngle // (? - tokLparenNameQuote // (?'name' - tokLparenFlags // (?flags - tokLparenAtomic // (?> - tokLparenPositiveLookahead // (?= - tokLparenPositiveLookbehind // (?<= - tokLparenNegativeLookahead // (?! - tokLparenNegativeLookbehind // (?= utf8.RuneSelf { - _, size := utf8.DecodeRuneInString(l.input[l.pos:]) - l.pushTok(tokChar, size) - l.maybeInsertConcat() - continue - } - switch ch { - case '\\': - l.scanEscape(false) - case '.': - l.pushTok(tokDot, 1) - case '+': - l.pushTok(tokPlus, 1) - case '*': - l.pushTok(tokStar, 1) - case '^': - l.pushTok(tokCaret, 1) - case '$': - l.pushTok(tokDollar, 1) - case '?': - l.pushTok(tokQuestion, 1) - case ')': - l.pushTok(tokRparen, 1) - case '|': - l.pushTok(tokPipe, 1) - case '[': - if l.byteAt(l.pos+1) == '^' { - l.pushTok(tokLbracketCaret, 2) - } else { - l.pushTok(tokLbracket, 1) - } - l.scanCharClass() - case '(': - if l.byteAt(l.pos+1) == '?' { - switch { - case l.byteAt(l.pos+2) == '>': - l.pushTok(tokLparenAtomic, len("(?>")) - case l.byteAt(l.pos+2) == '=': - l.pushTok(tokLparenPositiveLookahead, len("(?=")) - case l.byteAt(l.pos+2) == '!': - l.pushTok(tokLparenNegativeLookahead, len("(?!")) - case l.byteAt(l.pos+2) == '<' && l.byteAt(l.pos+3) == '=': - l.pushTok(tokLparenPositiveLookbehind, len("(?<=")) - case l.byteAt(l.pos+2) == '<' && l.byteAt(l.pos+3) == '!': - l.pushTok(tokLparenNegativeLookbehind, len("(?= 0 { - l.pushTok(tokRepeat, len("{")+j) - } else { - l.pushTok(tokChar, 1) - } - default: - l.pushTok(tokChar, 1) - } - l.maybeInsertConcat() - } -} - -func (l *lexer) scanCharClass() { - l.maybeInsertConcat() - - // We need to handle first `]` in a special way. See #3. - if l.byteAt(l.pos) == ']' { - l.pushTok(tokChar, 1) - } - - for l.pos < len(l.input) { - ch := l.input[l.pos] - if ch >= utf8.RuneSelf { - _, size := utf8.DecodeRuneInString(l.input[l.pos:]) - l.pushTok(tokChar, size) - continue - } - switch ch { - case '\\': - l.scanEscape(true) - case '[': - isPosixClass := false - if l.byteAt(l.pos+1) == ':' { - j := l.stringIndex(l.pos+2, ":]") - if j >= 0 { - isPosixClass = true - l.pushTok(tokPosixClass, j+len("[::]")) - } - } - if !isPosixClass { - l.pushTok(tokChar, 1) - } - case '-': - l.pushTok(tokMinus, 1) - case ']': - l.pushTok(tokRbracket, 1) - return // Stop scanning in the char context - default: - l.pushTok(tokChar, 1) - } - } -} - -func (l *lexer) scanEscape(insideCharClass bool) { - s := l.input - if l.pos+1 >= len(s) { - throw(newPos(l.pos, l.pos+1), `unexpected end of pattern: trailing '\'`) - } - switch { - case s[l.pos+1] == 'p' || s[l.pos+1] == 'P': - if l.pos+2 >= len(s) { - throw(newPos(l.pos, l.pos+2), "unexpected end of pattern: expected uni-class-short or '{'") - } - if s[l.pos+2] == '{' { - j := strings.IndexByte(s[l.pos+2:], '}') - if j < 0 { - throw(newPos(l.pos, l.pos+2), "can't find closing '}'") - } - l.pushTok(tokEscapeUniFull, len(`\p{`)+j) - } else { - l.pushTok(tokEscapeUni, len(`\pL`)) - } - case s[l.pos+1] == 'x': - if l.pos+2 >= len(s) { - throw(newPos(l.pos, l.pos+2), "unexpected end of pattern: expected hex-digit or '{'") - } - if s[l.pos+2] == '{' { - j := strings.IndexByte(s[l.pos+2:], '}') - if j < 0 { - throw(newPos(l.pos, l.pos+2), "can't find closing '}'") - } - l.pushTok(tokEscapeHexFull, len(`\x{`)+j) - } else { - if isHexDigit(l.byteAt(l.pos + 3)) { - l.pushTok(tokEscapeHex, len(`\xFF`)) - } else { - l.pushTok(tokEscapeHex, len(`\xF`)) - } - } - case isOctalDigit(s[l.pos+1]): - digits := 1 - if isOctalDigit(l.byteAt(l.pos + 2)) { - if isOctalDigit(l.byteAt(l.pos + 3)) { - digits = 3 - } else { - digits = 2 - } - } - l.pushTok(tokEscapeOctal, len(`\`)+digits) - case s[l.pos+1] == 'Q': - size := len(s) - l.pos // Until the pattern ends - j := l.stringIndex(l.pos+2, `\E`) - if j >= 0 { - size = j + len(`\Q\E`) - } - l.pushTok(tokQ, size) - - default: - ch := l.byteAt(l.pos + 1) - if ch >= utf8.RuneSelf { - _, size := utf8.DecodeRuneInString(l.input[l.pos+1:]) - l.pushTok(tokEscapeChar, len(`\`)+size) - return - } - kind := tokEscapeChar - if insideCharClass { - if charClassMetachar[ch] { - kind = tokEscapeMeta - } - } else { - if reMetachar[ch] { - kind = tokEscapeMeta - } - } - l.pushTok(kind, 2) - } -} - -func (l *lexer) maybeInsertConcat() { - if l.isConcatPos() { - last := len(l.tokens) - 1 - tok := l.tokens[last] - l.tokens[last].kind = tokConcat - l.tokens = append(l.tokens, tok) - } -} - -func (l *lexer) Init(s string) { - l.pos = 0 - l.tokens = l.tokens[:0] - l.input = s - - l.scan() - - l.pos = 0 -} - -func (l *lexer) tryScanGroupName(pos int) bool { - tok := tokLparenName - endCh := byte('>') - offset := 1 - switch l.byteAt(pos) { - case '\'': - endCh = '\'' - tok = tokLparenNameQuote - case '<': - tok = tokLparenNameAngle - case 'P': - offset = 2 - default: - return false - } - if pos+offset >= len(l.input) { - return false - } - end := strings.IndexByte(l.input[pos+offset:], endCh) - if end < 0 { - return false - } - l.pushTok(tok, len("(?")+offset+end+1) - return true -} - -func (l *lexer) tryScanGroupFlags(pos int) bool { - colonPos := strings.IndexByte(l.input[pos:], ':') - parenPos := strings.IndexByte(l.input[pos:], ')') - if parenPos < 0 { - return false - } - end := parenPos - if colonPos >= 0 && colonPos < parenPos { - end = colonPos + len(":") - } - l.pushTok(tokLparenFlags, len("(?")+end) - return true -} - -func (l *lexer) tryScanComment(pos int) bool { - if l.byteAt(pos) != '#' { - return false - } - parenPos := strings.IndexByte(l.input[pos:], ')') - if parenPos < 0 { - return false - } - l.pushTok(tokComment, len("(?")+parenPos+len(")")) - return true -} - -func (l *lexer) repeatWidth(pos int) int { - j := pos - for isDigit(l.byteAt(j)) { - j++ - } - if j == pos { - return -1 - } - if l.byteAt(j) == '}' { - return (j + len("}")) - pos // {min} - } - if l.byteAt(j) != ',' { - return -1 - } - j += len(",") - for isDigit(l.byteAt(j)) { - j++ - } - if l.byteAt(j) == '}' { - return (j + len("}")) - pos // {min,} or {min,max} - } - return -1 -} - -func (l *lexer) stringIndex(offset int, s string) int { - if offset < len(l.input) { - return strings.Index(l.input[offset:], s) - } - return -1 -} - -func (l *lexer) byteAt(pos int) byte { - if pos >= 0 && pos < len(l.input) { - return l.input[pos] - } - return 0 -} - -func (l *lexer) pushTok(kind tokenKind, size int) { - l.tokens = append(l.tokens, token{ - kind: kind, - pos: Position{Begin: uint16(l.pos), End: uint16(l.pos + size)}, - }) - l.pos += size -} - -func (l *lexer) isConcatPos() bool { - if len(l.tokens) < 2 { - return false - } - x := l.tokens[len(l.tokens)-2].kind - if concatTable[x]&concatX != 0 { - return false - } - y := l.tokens[len(l.tokens)-1].kind - return concatTable[y]&concatY == 0 -} - -const ( - concatX byte = 1 << iota - concatY -) - -var concatTable = [256]byte{ - tokPipe: concatX | concatY, - - tokLparen: concatX, - tokLparenFlags: concatX, - tokLparenName: concatX, - tokLparenNameAngle: concatX, - tokLparenNameQuote: concatX, - tokLparenAtomic: concatX, - tokLbracket: concatX, - tokLbracketCaret: concatX, - tokLparenPositiveLookahead: concatX, - tokLparenPositiveLookbehind: concatX, - tokLparenNegativeLookahead: concatX, - tokLparenNegativeLookbehind: concatX, - - tokRparen: concatY, - tokRbracket: concatY, - tokPlus: concatY, - tokStar: concatY, - tokQuestion: concatY, - tokRepeat: concatY, -} diff --git a/vendor/github.com/quasilyte/regex/syntax/operation.go b/vendor/github.com/quasilyte/regex/syntax/operation.go deleted file mode 100644 index 0fc8fc521..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/operation.go +++ /dev/null @@ -1,195 +0,0 @@ -package syntax - -//go:generate stringer -type=Operation -trimprefix=Op -const ( - OpNone Operation = iota - - // OpConcat is a concatenation of ops. - // Examples: `xy` `abc\d` `` - // Args - concatenated ops - // - // As a special case, OpConcat with 0 Args is used for "empty" - // set of operations. - OpConcat - - // OpDot is a '.' wildcard. - OpDot - - // OpAlt is x|y alternation of ops. - // Examples: `a|bc` `x(.*?)|y(.*?)` - // Args - union-connected regexp branches - OpAlt - - // OpStar is a shorthand for {0,} repetition. - // Examples: `x*` - // Args[0] - repeated expression - OpStar - - // OpPlus is a shorthand for {1,} repetition. - // Examples: `x+` - // Args[0] - repeated expression - OpPlus - - // OpQuestion is a shorthand for {0,1} repetition. - // Examples: `x?` - // Args[0] - repeated expression - OpQuestion - - // OpNonGreedy makes its operand quantifier non-greedy. - // Examples: `x??` `x*?` `x+?` - // Args[0] - quantified expression - OpNonGreedy - - // OpPossessive makes its operand quantifier possessive. - // Examples: `x?+` `x*+` `x++` - // Args[0] - quantified expression - OpPossessive - - // OpCaret is ^ anchor. - OpCaret - - // OpDollar is $ anchor. - OpDollar - - // OpLiteral is a collection of consecutive chars. - // Examples: `ab` `10x` - // Args - enclosed characters (OpChar) - OpLiteral - - // OpChar is a single literal pattern character. - // Examples: `a` `6` `ф` - OpChar - - // OpString is an artificial element that is used in other expressions. - OpString - - // OpQuote is a \Q...\E enclosed literal. - // Examples: `\Q.?\E` `\Q?q[]=1` - // FormQuoteUnclosed: `\Qabc` - // Args[0] - literal value (OpString) - OpQuote - - // OpEscapeChar is a single char escape. - // Examples: `\d` `\a` `\n` - // Args[0] - escaped value (OpString) - OpEscapeChar - - // OpEscapeMeta is an escaped meta char. - // Examples: `\(` `\[` `\+` - // Args[0] - escaped value (OpString) - OpEscapeMeta - - // OpEscapeOctal is an octal char code escape (up to 3 digits). - // Examples: `\123` `\12` - // Args[0] - escaped value (OpString) - OpEscapeOctal - - // OpEscapeHex is a hex char code escape. - // Examples: `\x7F` `\xF7` - // FormEscapeHexFull examples: `\x{10FFFF}` `\x{F}`. - // Args[0] - escaped value (OpString) - OpEscapeHex - - // OpEscapeUni is a Unicode char class escape. - // Examples: `\pS` `\pL` `\PL` - // FormEscapeUniFull examples: `\p{Greek}` `\p{Symbol}` `\p{^L}` - // Args[0] - escaped value (OpString) - OpEscapeUni - - // OpCharClass is a char class enclosed in []. - // Examples: `[abc]` `[a-z0-9\]]` - // Args - char class elements (can include OpCharRange and OpPosixClass) - OpCharClass - - // OpNegCharClass is a negated char class enclosed in []. - // Examples: `[^abc]` `[^a-z0-9\]]` - // Args - char class elements (can include OpCharRange and OpPosixClass) - OpNegCharClass - - // OpCharRange is an inclusive char range inside a char class. - // Examples: `0-9` `A-Z` - // Args[0] - range lower bound - // Args[1] - range upper bound - OpCharRange - - // OpPosixClass is a named ASCII char set inside a char class. - // Examples: `[:alpha:]` `[:blank:]` - OpPosixClass - - // OpRepeat is a {min,max} repetition quantifier. - // Examples: `x{5}` `x{min,max}` `x{min,}` - // Args[0] - repeated expression - // Args[1] - repeat count (OpString) - OpRepeat - - // OpCapture is `(re)` capturing group. - // Examples: `(abc)` `(x|y)` - // Args[0] - enclosed expression - OpCapture - - // OpNamedCapture is `(?Pre)` capturing group. - // Examples: `(?Pabc)` `(?Px|y)` - // FormNamedCaptureAngle examples: `(?abc)` `(?x|y)` - // FormNamedCaptureQuote examples: `(?'foo'abc)` `(?'name'x|y)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - // Args[1] - group name (OpString) - OpNamedCapture - - // OpGroup is `(?:re)` non-capturing group. - // Examples: `(?:abc)` `(?:x|y)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - OpGroup - - // OpGroupWithFlags is `(?flags:re)` non-capturing group. - // Examples: `(?i:abc)` `(?i:x|y)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - // Args[1] - flags (OpString) - OpGroupWithFlags - - // OpAtomicGroup is `(?>re)` non-capturing group without backtracking. - // Examples: `(?>foo)` `(?>)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - OpAtomicGroup - - // OpPositiveLookahead is `(?=re)` asserts that following text matches re. - // Examples: `(?=foo)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - OpPositiveLookahead - - // OpNegativeLookahead is `(?!re)` asserts that following text doesn't match re. - // Examples: `(?!foo)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - OpNegativeLookahead - - // OpPositiveLookbehind is `(?<=re)` asserts that preceding text matches re. - // Examples: `(?<=foo)` - // Args[0] - enclosed expression (OpConcat with 0 args for empty group) - OpPositiveLookbehind - - // OpNegativeLookbehind is `(?=re)` asserts that preceding text doesn't match re. - // Examples: `(?= Operation(len(_Operation_index)-1) { - return "Operation(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _Operation_name[_Operation_index[i]:_Operation_index[i+1]] -} diff --git a/vendor/github.com/quasilyte/regex/syntax/parser.go b/vendor/github.com/quasilyte/regex/syntax/parser.go deleted file mode 100644 index f1c154f31..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/parser.go +++ /dev/null @@ -1,503 +0,0 @@ -package syntax - -import ( - "errors" - "strings" -) - -type ParserOptions struct { - // NoLiterals disables OpChar merging into OpLiteral. - NoLiterals bool -} - -func NewParser(opts *ParserOptions) *Parser { - return newParser(opts) -} - -type Parser struct { - out Regexp - lexer lexer - exprPool []Expr - - prefixParselets [256]prefixParselet - infixParselets [256]infixParselet - - charClass []Expr - allocated uint - - opts ParserOptions -} - -// ParsePCRE parses PHP-style pattern with delimiters. -// An example of such pattern is `/foo/i`. -func (p *Parser) ParsePCRE(pattern string) (*RegexpPCRE, error) { - pcre, err := p.newPCRE(pattern) - if err != nil { - return nil, err - } - if pcre.HasModifier('x') { - return nil, errors.New("'x' modifier is not supported") - } - re, err := p.Parse(pcre.Pattern) - if re != nil { - pcre.Expr = re.Expr - } - return pcre, err -} - -func (p *Parser) Parse(pattern string) (result *Regexp, err error) { - defer func() { - r := recover() - if r == nil { - return - } - if err2, ok := r.(ParseError); ok { - err = err2 - return - } - panic(r) - }() - - p.lexer.Init(pattern) - p.allocated = 0 - p.out.Pattern = pattern - if pattern == "" { - p.out.Expr = *p.newExpr(OpConcat, Position{}) - } else { - p.out.Expr = *p.parseExpr(0) - } - - if !p.opts.NoLiterals { - p.mergeChars(&p.out.Expr) - } - p.setValues(&p.out.Expr) - - return &p.out, nil -} - -type prefixParselet func(token) *Expr - -type infixParselet func(*Expr, token) *Expr - -func newParser(opts *ParserOptions) *Parser { - var p Parser - - if opts != nil { - p.opts = *opts - } - p.exprPool = make([]Expr, 256) - - for tok, op := range tok2op { - if op != 0 { - p.prefixParselets[tokenKind(tok)] = p.parsePrefixElementary - } - } - - p.prefixParselets[tokQ] = func(tok token) *Expr { - litPos := tok.pos - litPos.Begin += uint16(len(`\Q`)) - form := FormQuoteUnclosed - if strings.HasSuffix(p.tokenValue(tok), `\E`) { - litPos.End -= uint16(len(`\E`)) - form = FormDefault - } - lit := p.newExpr(OpString, litPos) - return p.newExprForm(OpQuote, form, tok.pos, lit) - } - - p.prefixParselets[tokEscapeHexFull] = func(tok token) *Expr { - litPos := tok.pos - litPos.Begin += uint16(len(`\x{`)) - litPos.End -= uint16(len(`}`)) - lit := p.newExpr(OpString, litPos) - return p.newExprForm(OpEscapeHex, FormEscapeHexFull, tok.pos, lit) - } - p.prefixParselets[tokEscapeUniFull] = func(tok token) *Expr { - litPos := tok.pos - litPos.Begin += uint16(len(`\p{`)) - litPos.End -= uint16(len(`}`)) - lit := p.newExpr(OpString, litPos) - return p.newExprForm(OpEscapeUni, FormEscapeUniFull, tok.pos, lit) - } - - p.prefixParselets[tokEscapeHex] = func(tok token) *Expr { return p.parseEscape(OpEscapeHex, `\x`, tok) } - p.prefixParselets[tokEscapeOctal] = func(tok token) *Expr { return p.parseEscape(OpEscapeOctal, `\`, tok) } - p.prefixParselets[tokEscapeChar] = func(tok token) *Expr { return p.parseEscape(OpEscapeChar, `\`, tok) } - p.prefixParselets[tokEscapeMeta] = func(tok token) *Expr { return p.parseEscape(OpEscapeMeta, `\`, tok) } - p.prefixParselets[tokEscapeUni] = func(tok token) *Expr { return p.parseEscape(OpEscapeUni, `\p`, tok) } - - p.prefixParselets[tokLparen] = func(tok token) *Expr { return p.parseGroup(OpCapture, tok) } - p.prefixParselets[tokLparenAtomic] = func(tok token) *Expr { return p.parseGroup(OpAtomicGroup, tok) } - p.prefixParselets[tokLparenPositiveLookahead] = func(tok token) *Expr { return p.parseGroup(OpPositiveLookahead, tok) } - p.prefixParselets[tokLparenNegativeLookahead] = func(tok token) *Expr { return p.parseGroup(OpNegativeLookahead, tok) } - p.prefixParselets[tokLparenPositiveLookbehind] = func(tok token) *Expr { return p.parseGroup(OpPositiveLookbehind, tok) } - p.prefixParselets[tokLparenNegativeLookbehind] = func(tok token) *Expr { return p.parseGroup(OpNegativeLookbehind, tok) } - - p.prefixParselets[tokLparenName] = func(tok token) *Expr { - return p.parseNamedCapture(FormDefault, tok) - } - p.prefixParselets[tokLparenNameAngle] = func(tok token) *Expr { - return p.parseNamedCapture(FormNamedCaptureAngle, tok) - } - p.prefixParselets[tokLparenNameQuote] = func(tok token) *Expr { - return p.parseNamedCapture(FormNamedCaptureQuote, tok) - } - - p.prefixParselets[tokLparenFlags] = p.parseGroupWithFlags - - p.prefixParselets[tokPipe] = func(tok token) *Expr { - // We need prefix pipe parselet to handle `(|x)` syntax. - right := p.parseExpr(1) - return p.newExpr(OpAlt, tok.pos, p.newEmpty(tok.pos), right) - } - p.prefixParselets[tokLbracket] = func(tok token) *Expr { - return p.parseCharClass(OpCharClass, tok) - } - p.prefixParselets[tokLbracketCaret] = func(tok token) *Expr { - return p.parseCharClass(OpNegCharClass, tok) - } - - p.infixParselets[tokRepeat] = func(left *Expr, tok token) *Expr { - repeatLit := p.newExpr(OpString, tok.pos) - return p.newExpr(OpRepeat, combinePos(left.Pos, tok.pos), left, repeatLit) - } - p.infixParselets[tokStar] = func(left *Expr, tok token) *Expr { - return p.newExpr(OpStar, combinePos(left.Pos, tok.pos), left) - } - p.infixParselets[tokConcat] = func(left *Expr, tok token) *Expr { - right := p.parseExpr(2) - if left.Op == OpConcat { - left.Args = append(left.Args, *right) - left.Pos.End = right.End() - return left - } - return p.newExpr(OpConcat, combinePos(left.Pos, right.Pos), left, right) - } - p.infixParselets[tokPipe] = p.parseAlt - p.infixParselets[tokMinus] = p.parseMinus - p.infixParselets[tokPlus] = p.parsePlus - p.infixParselets[tokQuestion] = p.parseQuestion - - return &p -} - -func (p *Parser) setValues(e *Expr) { - for i := range e.Args { - p.setValues(&e.Args[i]) - } - e.Value = p.exprValue(e) -} - -func (p *Parser) tokenValue(tok token) string { - return p.out.Pattern[tok.pos.Begin:tok.pos.End] -} - -func (p *Parser) exprValue(e *Expr) string { - return p.out.Pattern[e.Begin():e.End()] -} - -func (p *Parser) mergeChars(e *Expr) { - for i := range e.Args { - p.mergeChars(&e.Args[i]) - } - if e.Op != OpConcat || len(e.Args) < 2 { - return - } - - args := e.Args[:0] - i := 0 - for i < len(e.Args) { - first := i - chars := 0 - for j := i; j < len(e.Args) && e.Args[j].Op == OpChar; j++ { - chars++ - } - if chars > 1 { - c1 := e.Args[first] - c2 := e.Args[first+chars-1] - lit := p.newExpr(OpLiteral, combinePos(c1.Pos, c2.Pos)) - for j := 0; j < chars; j++ { - lit.Args = append(lit.Args, e.Args[first+j]) - } - args = append(args, *lit) - i += chars - } else { - args = append(args, e.Args[i]) - i++ - } - } - if len(args) == 1 { - *e = args[0] // Turn OpConcat into OpLiteral - } else { - e.Args = args - } -} - -func (p *Parser) newEmpty(pos Position) *Expr { - return p.newExpr(OpConcat, pos) -} - -func (p *Parser) newExprForm(op Operation, form Form, pos Position, args ...*Expr) *Expr { - e := p.newExpr(op, pos, args...) - e.Form = form - return e -} - -func (p *Parser) newExpr(op Operation, pos Position, args ...*Expr) *Expr { - e := p.allocExpr() - *e = Expr{ - Op: op, - Pos: pos, - Args: e.Args[:0], - } - for _, arg := range args { - e.Args = append(e.Args, *arg) - } - return e -} - -func (p *Parser) allocExpr() *Expr { - i := p.allocated - if i < uint(len(p.exprPool)) { - p.allocated++ - return &p.exprPool[i] - } - return &Expr{} -} - -func (p *Parser) expect(kind tokenKind) Position { - tok := p.lexer.NextToken() - if tok.kind != kind { - throwExpectedFound(tok.pos, kind.String(), tok.kind.String()) - } - return tok.pos -} - -func (p *Parser) parseExpr(precedence int) *Expr { - tok := p.lexer.NextToken() - prefix := p.prefixParselets[tok.kind] - if prefix == nil { - throwUnexpectedToken(tok.pos, tok.String()) - } - left := prefix(tok) - - for precedence < p.precedenceOf(p.lexer.Peek()) { - tok := p.lexer.NextToken() - infix := p.infixParselets[tok.kind] - left = infix(left, tok) - } - - return left -} - -func (p *Parser) parsePrefixElementary(tok token) *Expr { - return p.newExpr(tok2op[tok.kind], tok.pos) -} - -func (p *Parser) parseCharClass(op Operation, tok token) *Expr { - var endPos Position - p.charClass = p.charClass[:0] - for { - p.charClass = append(p.charClass, *p.parseExpr(0)) - next := p.lexer.Peek() - if next.kind == tokRbracket { - endPos = next.pos - p.lexer.NextToken() - break - } - if next.kind == tokNone { - throw(tok.pos, "unterminated '['") - } - } - - result := p.newExpr(op, combinePos(tok.pos, endPos)) - result.Args = append(result.Args, p.charClass...) - return result -} - -func (p *Parser) parseMinus(left *Expr, tok token) *Expr { - if p.isValidCharRangeOperand(left) { - if p.lexer.Peek().kind != tokRbracket { - right := p.parseExpr(2) - return p.newExpr(OpCharRange, combinePos(left.Pos, right.Pos), left, right) - } - } - p.charClass = append(p.charClass, *left) - return p.newExpr(OpChar, tok.pos) -} - -func (p *Parser) isValidCharRangeOperand(e *Expr) bool { - switch e.Op { - case OpEscapeHex, OpEscapeOctal, OpEscapeMeta, OpChar: - return true - case OpEscapeChar: - switch p.exprValue(e) { - case `\\`, `\|`, `\*`, `\+`, `\?`, `\.`, `\[`, `\^`, `\$`, `\(`, `\)`: - return true - } - } - return false -} - -func (p *Parser) parsePlus(left *Expr, tok token) *Expr { - op := OpPlus - switch left.Op { - case OpPlus, OpStar, OpQuestion, OpRepeat: - op = OpPossessive - } - return p.newExpr(op, combinePos(left.Pos, tok.pos), left) -} - -func (p *Parser) parseQuestion(left *Expr, tok token) *Expr { - op := OpQuestion - switch left.Op { - case OpPlus, OpStar, OpQuestion, OpRepeat: - op = OpNonGreedy - } - return p.newExpr(op, combinePos(left.Pos, tok.pos), left) -} - -func (p *Parser) parseAlt(left *Expr, tok token) *Expr { - var right *Expr - switch p.lexer.Peek().kind { - case tokRparen, tokNone: - // This is needed to handle `(x|)` syntax. - right = p.newEmpty(tok.pos) - default: - right = p.parseExpr(1) - } - if left.Op == OpAlt { - left.Args = append(left.Args, *right) - left.Pos.End = right.End() - return left - } - return p.newExpr(OpAlt, combinePos(left.Pos, right.Pos), left, right) -} - -func (p *Parser) parseGroupItem(tok token) *Expr { - if p.lexer.Peek().kind == tokRparen { - // This is needed to handle `() syntax.` - return p.newEmpty(tok.pos) - } - return p.parseExpr(0) -} - -func (p *Parser) parseGroup(op Operation, tok token) *Expr { - x := p.parseGroupItem(tok) - result := p.newExpr(op, tok.pos, x) - result.Pos.End = p.expect(tokRparen).End - return result -} - -func (p *Parser) parseNamedCapture(form Form, tok token) *Expr { - prefixLen := len("(?<") - if form == FormDefault { - prefixLen = len("(?P<") - } - name := p.newExpr(OpString, Position{ - Begin: tok.pos.Begin + uint16(prefixLen), - End: tok.pos.End - uint16(len(">")), - }) - x := p.parseGroupItem(tok) - result := p.newExprForm(OpNamedCapture, form, tok.pos, x, name) - result.Pos.End = p.expect(tokRparen).End - return result -} - -func (p *Parser) parseGroupWithFlags(tok token) *Expr { - var result *Expr - val := p.out.Pattern[tok.pos.Begin+1 : tok.pos.End] - switch { - case !strings.HasSuffix(val, ":"): - flags := p.newExpr(OpString, Position{ - Begin: tok.pos.Begin + uint16(len("(?")), - End: tok.pos.End, - }) - result = p.newExpr(OpFlagOnlyGroup, tok.pos, flags) - case val == "?:": - x := p.parseGroupItem(tok) - result = p.newExpr(OpGroup, tok.pos, x) - default: - flags := p.newExpr(OpString, Position{ - Begin: tok.pos.Begin + uint16(len("(?")), - End: tok.pos.End - uint16(len(":")), - }) - x := p.parseGroupItem(tok) - result = p.newExpr(OpGroupWithFlags, tok.pos, x, flags) - } - result.Pos.End = p.expect(tokRparen).End - return result -} - -func (p *Parser) parseEscape(op Operation, prefix string, tok token) *Expr { - litPos := tok.pos - litPos.Begin += uint16(len(prefix)) - lit := p.newExpr(OpString, litPos) - return p.newExpr(op, tok.pos, lit) -} - -func (p *Parser) precedenceOf(tok token) int { - switch tok.kind { - case tokPipe: - return 1 - case tokConcat, tokMinus: - return 2 - case tokPlus, tokStar, tokQuestion, tokRepeat: - return 3 - default: - return 0 - } -} - -func (p *Parser) newPCRE(source string) (*RegexpPCRE, error) { - if source == "" { - return nil, errors.New("empty pattern: can't find delimiters") - } - - delim := source[0] - endDelim := delim - switch delim { - case '(': - endDelim = ')' - case '{': - endDelim = '}' - case '[': - endDelim = ']' - case '<': - endDelim = '>' - case '\\': - return nil, errors.New("'\\' is not a valid delimiter") - default: - if isSpace(delim) { - return nil, errors.New("whitespace is not a valid delimiter") - } - if isAlphanumeric(delim) { - return nil, errors.New("'" + string(delim) + "' is not a valid delimiter") - } - } - - const delimLen = 1 - j := strings.LastIndexByte(source[delimLen:], endDelim) - if j == -1 { - return nil, errors.New("can't find '" + string(endDelim) + "' ending delimiter") - } - j += delimLen - - pcre := &RegexpPCRE{ - Pattern: source[delimLen:j], - Source: source, - Delim: [2]byte{delim, endDelim}, - Modifiers: source[j+delimLen:], - } - return pcre, nil -} - -var tok2op = [256]Operation{ - tokDollar: OpDollar, - tokCaret: OpCaret, - tokDot: OpDot, - tokChar: OpChar, - tokMinus: OpChar, - tokPosixClass: OpPosixClass, - tokComment: OpComment, -} diff --git a/vendor/github.com/quasilyte/regex/syntax/pos.go b/vendor/github.com/quasilyte/regex/syntax/pos.go deleted file mode 100644 index 51bdbf87a..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/pos.go +++ /dev/null @@ -1,10 +0,0 @@ -package syntax - -type Position struct { - Begin uint16 - End uint16 -} - -func combinePos(begin, end Position) Position { - return Position{Begin: begin.Begin, End: end.End} -} diff --git a/vendor/github.com/quasilyte/regex/syntax/tokenkind_string.go b/vendor/github.com/quasilyte/regex/syntax/tokenkind_string.go deleted file mode 100644 index 8800436bc..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/tokenkind_string.go +++ /dev/null @@ -1,59 +0,0 @@ -// Code generated by "stringer -type=tokenKind -trimprefix=tok -linecomment=true"; DO NOT EDIT. - -package syntax - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[tokNone-0] - _ = x[tokChar-1] - _ = x[tokGroupFlags-2] - _ = x[tokPosixClass-3] - _ = x[tokConcat-4] - _ = x[tokRepeat-5] - _ = x[tokEscapeChar-6] - _ = x[tokEscapeMeta-7] - _ = x[tokEscapeOctal-8] - _ = x[tokEscapeUni-9] - _ = x[tokEscapeUniFull-10] - _ = x[tokEscapeHex-11] - _ = x[tokEscapeHexFull-12] - _ = x[tokComment-13] - _ = x[tokQ-14] - _ = x[tokMinus-15] - _ = x[tokLbracket-16] - _ = x[tokLbracketCaret-17] - _ = x[tokRbracket-18] - _ = x[tokDollar-19] - _ = x[tokCaret-20] - _ = x[tokQuestion-21] - _ = x[tokDot-22] - _ = x[tokPlus-23] - _ = x[tokStar-24] - _ = x[tokPipe-25] - _ = x[tokLparen-26] - _ = x[tokLparenName-27] - _ = x[tokLparenNameAngle-28] - _ = x[tokLparenNameQuote-29] - _ = x[tokLparenFlags-30] - _ = x[tokLparenAtomic-31] - _ = x[tokLparenPositiveLookahead-32] - _ = x[tokLparenPositiveLookbehind-33] - _ = x[tokLparenNegativeLookahead-34] - _ = x[tokLparenNegativeLookbehind-35] - _ = x[tokRparen-36] -} - -const _tokenKind_name = "NoneCharGroupFlagsPosixClassConcatRepeatEscapeCharEscapeMetaEscapeOctalEscapeUniEscapeUniFullEscapeHexEscapeHexFullComment\\Q-[[^]$^?.+*|((?P(?(?'name'(?flags(?>(?=(?<=(?!(?= tokenKind(len(_tokenKind_index)-1) { - return "tokenKind(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _tokenKind_name[_tokenKind_index[i]:_tokenKind_index[i+1]] -} diff --git a/vendor/github.com/quasilyte/regex/syntax/utils.go b/vendor/github.com/quasilyte/regex/syntax/utils.go deleted file mode 100644 index e5b654825..000000000 --- a/vendor/github.com/quasilyte/regex/syntax/utils.go +++ /dev/null @@ -1,30 +0,0 @@ -package syntax - -func isSpace(ch byte) bool { - switch ch { - case '\r', '\n', '\t', '\f', '\v', ' ': - return true - default: - return false - } -} - -func isAlphanumeric(ch byte) bool { - return (ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') -} - -func isDigit(ch byte) bool { - return ch >= '0' && ch <= '9' -} - -func isOctalDigit(ch byte) bool { - return ch >= '0' && ch <= '7' -} - -func isHexDigit(ch byte) bool { - return (ch >= '0' && ch <= '9') || - (ch >= 'a' && ch <= 'f') || - (ch >= 'A' && ch <= 'F') -} diff --git a/vendor/github.com/quasilyte/stdinfo/LICENSE b/vendor/github.com/quasilyte/stdinfo/LICENSE deleted file mode 100644 index 87a453862..000000000 --- a/vendor/github.com/quasilyte/stdinfo/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Iskander (Alex) Sharipov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/quasilyte/stdinfo/stdinfo.go b/vendor/github.com/quasilyte/stdinfo/stdinfo.go deleted file mode 100644 index 040f63445..000000000 --- a/vendor/github.com/quasilyte/stdinfo/stdinfo.go +++ /dev/null @@ -1,30 +0,0 @@ -package stdinfo - -type Package struct { - // Name is a package name. - // For "encoding/json" the package name is "json". - Name string - - // Path is a package path, like "encoding/json". - Path string - - // Freq is a package import frequency approximation. - // A value of -1 means "unknown". - Freq int -} - -// PathByName maps a std package name to its package path. -// -// For packages with multiple choices, like "template", -// only the more common one is accessible ("text/template" in this case). -// -// This map doesn't contain extremely rare packages either. -// Use PackageList variable if you want to construct a different mapping. -// -// It's exported as map to make it easier to re-use it in libraries -// without copying. -var PathByName = generatedPathByName - -// PackagesList is a list of std packages information. -// It's sorted by a package name. -var PackagesList = generatedPackagesList diff --git a/vendor/github.com/quasilyte/stdinfo/stdinfo_gen.go b/vendor/github.com/quasilyte/stdinfo/stdinfo_gen.go deleted file mode 100644 index ecfff9b6c..000000000 --- a/vendor/github.com/quasilyte/stdinfo/stdinfo_gen.go +++ /dev/null @@ -1,274 +0,0 @@ -// Code generated by "script/gen.go"; DO NOT EDIT. - -package stdinfo - -var generatedPathByName = map[string]string{ - "fmt": "fmt", // Freq=15795 - "testing": "testing", // Freq=12807 - "context": "context", // Freq=10797 - "time": "time", // Freq=8900 - "strings": "strings", // Freq=8852 - "os": "os", // Freq=5712 - "bytes": "bytes", // Freq=4129 - "io": "io", // Freq=3981 - "http": "net/http", // Freq=3691 - "sync": "sync", // Freq=3492 - "errors": "errors", // Freq=3107 - "strconv": "strconv", // Freq=3076 - "reflect": "reflect", // Freq=3025 - "filepath": "path/filepath", // Freq=2843 - "json": "encoding/json", // Freq=2537 - "sort": "sort", // Freq=2382 - "ioutil": "io/ioutil", // Freq=2164 - "net": "net", // Freq=2025 - "math": "math", // Freq=1746 - "url": "net/url", // Freq=1411 - "regexp": "regexp", // Freq=1320 - "runtime": "runtime", // Freq=1318 - "log": "log", // Freq=1149 - "flag": "flag", // Freq=1002 - "path": "path", // Freq=993 - "unsafe": "unsafe", // Freq=992 - "rand": "math/rand", // Freq=981 - "syscall": "syscall", // Freq=902 - "atomic": "sync/atomic", // Freq=804 - "bufio": "bufio", // Freq=695 - "httptest": "net/http/httptest", // Freq=676 - "exec": "os/exec", // Freq=676 - "binary": "encoding/binary", // Freq=476 - "tls": "crypto/tls", // Freq=475 - "token": "go/token", // Freq=471 - "utf8": "unicode/utf8", // Freq=404 - "base64": "encoding/base64", // Freq=383 - "ast": "go/ast", // Freq=373 - "x509": "crypto/x509", // Freq=357 - "hex": "encoding/hex", // Freq=340 - "unicode": "unicode", // Freq=309 - "types": "go/types", // Freq=309 - "big": "math/big", // Freq=230 - "sha256": "crypto/sha256", // Freq=227 - "template": "text/template", // Freq=211 - "fs": "io/fs", // Freq=162 - "parser": "go/parser", // Freq=160 - "sql": "database/sql", // Freq=157 - "gzip": "compress/gzip", // Freq=150 - "signal": "os/signal", // Freq=139 - "pem": "encoding/pem", // Freq=137 - "hash": "hash", // Freq=137 - "crypto": "crypto", // Freq=132 - "build": "go/build", // Freq=121 - "debug": "runtime/debug", // Freq=121 - "bits": "math/bits", // Freq=120 - "constant": "go/constant", // Freq=120 - "xml": "encoding/xml", // Freq=118 - "tabwriter": "text/tabwriter", // Freq=116 - "md5": "crypto/md5", // Freq=110 - "rsa": "crypto/rsa", // Freq=103 - "format": "go/format", // Freq=88 - "sha1": "crypto/sha1", // Freq=85 - "driver": "database/sql/driver", // Freq=81 - "pkix": "crypto/x509/pkix", // Freq=80 - "heap": "container/heap", // Freq=78 - "tar": "archive/tar", // Freq=77 - "ecdsa": "crypto/ecdsa", // Freq=75 - "cipher": "crypto/cipher", // Freq=74 - "crc32": "hash/crc32", // Freq=70 - "gob": "encoding/gob", // Freq=65 - "elliptic": "crypto/elliptic", // Freq=60 - "subtle": "crypto/subtle", // Freq=54 - "zip": "archive/zip", // Freq=54 - "aes": "crypto/aes", // Freq=53 - "mime": "mime", // Freq=51 - "pprof": "runtime/pprof", // Freq=47 - "textproto": "net/textproto", // Freq=47 - "image": "image", // Freq=45 - "fnv": "hash/fnv", // Freq=45 - "hmac": "crypto/hmac", // Freq=45 - "httputil": "net/http/httputil", // Freq=44 - "elf": "debug/elf", // Freq=44 - "encoding": "encoding", // Freq=41 - "sha512": "crypto/sha512", // Freq=41 - "cmplx": "math/cmplx", // Freq=40 - "color": "image/color", // Freq=38 - "html": "html", // Freq=37 - "expvar": "expvar", // Freq=34 - "embed": "embed", // Freq=32 - "csv": "encoding/csv", // Freq=31 - "importer": "go/importer", // Freq=31 - "multipart": "mime/multipart", // Freq=30 - "printer": "go/printer", // Freq=27 - "syslog": "log/syslog", // Freq=27 - "asn1": "encoding/asn1", // Freq=27 - "list": "container/list", // Freq=27 - "scanner": "go/scanner", // Freq=25 - "ed25519": "crypto/ed25519", // Freq=25 - "dwarf": "debug/dwarf", // Freq=23 - "flate": "compress/flate", // Freq=22 - "zlib": "compress/zlib", // Freq=21 - "png": "image/png", // Freq=20 - "trace": "runtime/trace", // Freq=20 - "httptrace": "net/http/httptrace", // Freq=19 - "utf16": "unicode/utf16", // Freq=19 - "rpc": "net/rpc", // Freq=19 - "macho": "debug/macho", // Freq=16 - "iotest": "testing/iotest", // Freq=15 - "dsa": "crypto/dsa", // Freq=13 - "parse": "text/template/parse", // Freq=13 - "cookiejar": "net/http/cookiejar", // Freq=12 - "fstest": "testing/fstest", // Freq=11 - "jpeg": "image/jpeg", // Freq=11 -} - -var generatedPackagesList = []Package{ - {Name: "adler32", Path: "hash/adler32", Freq: 7}, - {Name: "aes", Path: "crypto/aes", Freq: 53}, - {Name: "ascii85", Path: "encoding/ascii85", Freq: -1}, - {Name: "asn1", Path: "encoding/asn1", Freq: 27}, - {Name: "ast", Path: "go/ast", Freq: 373}, - {Name: "atomic", Path: "sync/atomic", Freq: 804}, - {Name: "base32", Path: "encoding/base32", Freq: 5}, - {Name: "base64", Path: "encoding/base64", Freq: 383}, - {Name: "big", Path: "math/big", Freq: 230}, - {Name: "binary", Path: "encoding/binary", Freq: 476}, - {Name: "bits", Path: "math/bits", Freq: 120}, - {Name: "bufio", Path: "bufio", Freq: 695}, - {Name: "build", Path: "go/build", Freq: 121}, - {Name: "bytes", Path: "bytes", Freq: 4129}, - {Name: "bzip2", Path: "compress/bzip2", Freq: 7}, - {Name: "cgi", Path: "net/http/cgi", Freq: 1}, - {Name: "cgo", Path: "runtime/cgo", Freq: -1}, - {Name: "cipher", Path: "crypto/cipher", Freq: 74}, - {Name: "cmplx", Path: "math/cmplx", Freq: 40}, - {Name: "color", Path: "image/color", Freq: 38}, - {Name: "constant", Path: "go/constant", Freq: 120}, - {Name: "constraint", Path: "go/build/constraint", Freq: 5}, - {Name: "context", Path: "context", Freq: 10797}, - {Name: "cookiejar", Path: "net/http/cookiejar", Freq: 12}, - {Name: "crc32", Path: "hash/crc32", Freq: 70}, - {Name: "crc64", Path: "hash/crc64", Freq: 3}, - {Name: "crypto", Path: "crypto", Freq: 132}, - {Name: "csv", Path: "encoding/csv", Freq: 31}, - {Name: "debug", Path: "runtime/debug", Freq: 121}, - {Name: "des", Path: "crypto/des", Freq: 8}, - {Name: "doc", Path: "go/doc", Freq: 15}, - {Name: "draw", Path: "image/draw", Freq: 7}, - {Name: "driver", Path: "database/sql/driver", Freq: 81}, - {Name: "dsa", Path: "crypto/dsa", Freq: 13}, - {Name: "dwarf", Path: "debug/dwarf", Freq: 23}, - {Name: "ecdsa", Path: "crypto/ecdsa", Freq: 75}, - {Name: "ed25519", Path: "crypto/ed25519", Freq: 25}, - {Name: "elf", Path: "debug/elf", Freq: 44}, - {Name: "elliptic", Path: "crypto/elliptic", Freq: 60}, - {Name: "embed", Path: "embed", Freq: 32}, - {Name: "encoding", Path: "encoding", Freq: 41}, - {Name: "errors", Path: "errors", Freq: 3107}, - {Name: "exec", Path: "os/exec", Freq: 676}, - {Name: "expvar", Path: "expvar", Freq: 34}, - {Name: "fcgi", Path: "net/http/fcgi", Freq: 2}, - {Name: "filepath", Path: "path/filepath", Freq: 2843}, - {Name: "flag", Path: "flag", Freq: 1002}, - {Name: "flate", Path: "compress/flate", Freq: 22}, - {Name: "fmt", Path: "fmt", Freq: 15795}, - {Name: "fnv", Path: "hash/fnv", Freq: 45}, - {Name: "format", Path: "go/format", Freq: 88}, - {Name: "fs", Path: "io/fs", Freq: 162}, - {Name: "fstest", Path: "testing/fstest", Freq: 11}, - {Name: "gif", Path: "image/gif", Freq: 5}, - {Name: "gob", Path: "encoding/gob", Freq: 65}, - {Name: "gosym", Path: "debug/gosym", Freq: 3}, - {Name: "gzip", Path: "compress/gzip", Freq: 150}, - {Name: "hash", Path: "hash", Freq: 137}, - {Name: "heap", Path: "container/heap", Freq: 78}, - {Name: "hex", Path: "encoding/hex", Freq: 340}, - {Name: "hmac", Path: "crypto/hmac", Freq: 45}, - {Name: "html", Path: "html", Freq: 37}, - {Name: "http", Path: "net/http", Freq: 3691}, - {Name: "httptest", Path: "net/http/httptest", Freq: 676}, - {Name: "httptrace", Path: "net/http/httptrace", Freq: 19}, - {Name: "httputil", Path: "net/http/httputil", Freq: 44}, - {Name: "image", Path: "image", Freq: 45}, - {Name: "importer", Path: "go/importer", Freq: 31}, - {Name: "io", Path: "io", Freq: 3981}, - {Name: "iotest", Path: "testing/iotest", Freq: 15}, - {Name: "ioutil", Path: "io/ioutil", Freq: 2164}, - {Name: "jpeg", Path: "image/jpeg", Freq: 11}, - {Name: "json", Path: "encoding/json", Freq: 2537}, - {Name: "jsonrpc", Path: "net/rpc/jsonrpc", Freq: -1}, - {Name: "list", Path: "container/list", Freq: 27}, - {Name: "log", Path: "log", Freq: 1149}, - {Name: "lzw", Path: "compress/lzw", Freq: 3}, - {Name: "macho", Path: "debug/macho", Freq: 16}, - {Name: "mail", Path: "net/mail", Freq: 7}, - {Name: "maphash", Path: "hash/maphash", Freq: 1}, - {Name: "math", Path: "math", Freq: 1746}, - {Name: "md5", Path: "crypto/md5", Freq: 110}, - {Name: "metrics", Path: "runtime/metrics", Freq: 3}, - {Name: "mime", Path: "mime", Freq: 51}, - {Name: "multipart", Path: "mime/multipart", Freq: 30}, - {Name: "net", Path: "net", Freq: 2025}, - {Name: "os", Path: "os", Freq: 5712}, - {Name: "palette", Path: "image/color/palette", Freq: 4}, - {Name: "parse", Path: "text/template/parse", Freq: 13}, - {Name: "parser", Path: "go/parser", Freq: 160}, - {Name: "path", Path: "path", Freq: 993}, - {Name: "pe", Path: "debug/pe", Freq: 12}, - {Name: "pem", Path: "encoding/pem", Freq: 137}, - {Name: "pkix", Path: "crypto/x509/pkix", Freq: 80}, - {Name: "plan9obj", Path: "debug/plan9obj", Freq: 1}, - {Name: "plugin", Path: "plugin", Freq: 4}, - {Name: "png", Path: "image/png", Freq: 20}, - {Name: "pprof", Path: "runtime/pprof", Freq: 47}, - {Name: "pprof", Path: "net/http/pprof", Freq: 33}, - {Name: "printer", Path: "go/printer", Freq: 27}, - {Name: "quick", Path: "testing/quick", Freq: 51}, - {Name: "quotedprintable", Path: "mime/quotedprintable", Freq: 2}, - {Name: "race", Path: "runtime/race", Freq: -1}, - {Name: "rand", Path: "math/rand", Freq: 981}, - {Name: "rand", Path: "crypto/rand", Freq: 256}, - {Name: "rc4", Path: "crypto/rc4", Freq: 3}, - {Name: "reflect", Path: "reflect", Freq: 3025}, - {Name: "regexp", Path: "regexp", Freq: 1320}, - {Name: "ring", Path: "container/ring", Freq: 2}, - {Name: "rpc", Path: "net/rpc", Freq: 19}, - {Name: "rsa", Path: "crypto/rsa", Freq: 103}, - {Name: "runtime", Path: "runtime", Freq: 1318}, - {Name: "scanner", Path: "text/scanner", Freq: 23}, - {Name: "scanner", Path: "go/scanner", Freq: 25}, - {Name: "sha1", Path: "crypto/sha1", Freq: 85}, - {Name: "sha256", Path: "crypto/sha256", Freq: 227}, - {Name: "sha512", Path: "crypto/sha512", Freq: 41}, - {Name: "signal", Path: "os/signal", Freq: 139}, - {Name: "smtp", Path: "net/smtp", Freq: 6}, - {Name: "sort", Path: "sort", Freq: 2382}, - {Name: "sql", Path: "database/sql", Freq: 157}, - {Name: "strconv", Path: "strconv", Freq: 3076}, - {Name: "strings", Path: "strings", Freq: 8852}, - {Name: "subtle", Path: "crypto/subtle", Freq: 54}, - {Name: "suffixarray", Path: "index/suffixarray", Freq: 2}, - {Name: "sync", Path: "sync", Freq: 3492}, - {Name: "syntax", Path: "regexp/syntax", Freq: 11}, - {Name: "syscall", Path: "syscall", Freq: 902}, - {Name: "syslog", Path: "log/syslog", Freq: 27}, - {Name: "tabwriter", Path: "text/tabwriter", Freq: 116}, - {Name: "tar", Path: "archive/tar", Freq: 77}, - {Name: "template", Path: "html/template", Freq: 173}, - {Name: "template", Path: "text/template", Freq: 211}, - {Name: "testing", Path: "testing", Freq: 12807}, - {Name: "textproto", Path: "net/textproto", Freq: 47}, - {Name: "time", Path: "time", Freq: 8900}, - {Name: "tls", Path: "crypto/tls", Freq: 475}, - {Name: "token", Path: "go/token", Freq: 471}, - {Name: "trace", Path: "runtime/trace", Freq: 20}, - {Name: "types", Path: "go/types", Freq: 309}, - {Name: "tzdata", Path: "time/tzdata", Freq: 6}, - {Name: "unicode", Path: "unicode", Freq: 309}, - {Name: "unsafe", Path: "unsafe", Freq: 992}, - {Name: "url", Path: "net/url", Freq: 1411}, - {Name: "user", Path: "os/user", Freq: 51}, - {Name: "utf16", Path: "unicode/utf16", Freq: 19}, - {Name: "utf8", Path: "unicode/utf8", Freq: 404}, - {Name: "x509", Path: "crypto/x509", Freq: 357}, - {Name: "xml", Path: "encoding/xml", Freq: 118}, - {Name: "zip", Path: "archive/zip", Freq: 54}, - {Name: "zlib", Path: "compress/zlib", Freq: 21}, -} -- cgit mrf-deployment