Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var PrecompiledRules = &ir.File{ PkgPath: "gorules", CustomDecls: []string{}, BundleImports: []ir.BundleImport{}, RuleGroups: []ir.RuleGroup{ { Line: 15, Name: "unusedFormatting", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects unused formatting functionality", DocBefore: "fmt.Sprintf(\"42\")", DocAfter: "fmt.Sprint(\"42\")", Rules: []ir.Rule{{ Line: 16, SyntaxPatterns: []ir.PatternString{ {Line: 16, Value: "fmt.Sprintf($_)"}, {Line: 16, Value: "fmt.Errorf($_)"}, }, ReportTemplate: "use function alternative without formatting", }}, }, { Line: 24, Name: "nestedErrorCall", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects unnecessary nested calls for errors.New", DocBefore: "errors.New(fmt.Sprintf(\"foo: %s\", \"bar\"))", DocAfter: "fmt.Errorf(\"foo: %s\", \"bar\")", Rules: []ir.Rule{{ Line: 25, SyntaxPatterns: []ir.PatternString{{Line: 25, Value: "errors.New(fmt.Sprintf($*args))"}}, ReportTemplate: "use fmt.Errorf instead of nested calls", SuggestTemplate: "fmt.Errorf($args)", }}, }, { Line: 45, Name: "uncheckedTypeAssert", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Detects unchecked type assertation", DocBefore: "foo := bar.(string) // var bar interface{}", DocAfter: "foo, ok := bar.(string)", Rules: []ir.Rule{{ Line: 46, SyntaxPatterns: []ir.PatternString{ {Line: 47, Value: "$_ := $_.($_)"}, {Line: 48, Value: "$_ = $_.($_)"}, {Line: 49, Value: "$_($*_, $_.($_), $*_)"}, {Line: 50, Value: "$_{$*_, $_.($_), $*_}"}, {Line: 51, Value: "$_{$*_, $_: $_.($_), $*_}"}, {Line: 52, Value: "$_ <- $_.($_)"}, {Line: 53, Value: "$_{$*_, $_.($_): $_, $*_}"}, }, ReportTemplate: "avoid unchecked type assertions as they can panic", }}, }, { Line: 61, Name: "rangeCopyVal", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Detects copy big structs in loop body", DocBefore: "for _, x := range xs { myfunc(x) } // for example var xs [][2048]string", DocAfter: "for i := range xs { myfunc(xs[i]) }", Rules: []ir.Rule{{ Line: 62, SyntaxPatterns: []ir.PatternString{ {Line: 62, Value: "for $_, $x := range $xs { $*_ }"}, {Line: 62, Value: "for $_, $x = range $xs { $*_ }"}, }, ReportTemplate: "each iteration copies more than 256 bytes (consider pointers or indexing)", WhereExpr: ir.FilterExpr{ Line: 63, Op: ir.FilterAndOp, Src: "(m[\"xs\"].Type.Is(\"[]$_\") || m[\"xs\"].Type.Is(\"[$_]$_\")) && m[\"x\"].Type.Size >= 256", Args: []ir.FilterExpr{ { Line: 63, Op: ir.FilterOrOp, Src: "(m[\"xs\"].Type.Is(\"[]$_\") || m[\"xs\"].Type.Is(\"[$_]$_\"))", Args: []ir.FilterExpr{ { Line: 63, Op: ir.FilterVarTypeIsOp, Src: "m[\"xs\"].Type.Is(\"[]$_\")", Value: "xs", Args: []ir.FilterExpr{{Line: 63, Op: ir.FilterStringOp, Src: "\"[]$_\"", Value: "[]$_"}}, }, { Line: 63, Op: ir.FilterVarTypeIsOp, Src: "m[\"xs\"].Type.Is(\"[$_]$_\")", Value: "xs", Args: []ir.FilterExpr{{Line: 63, Op: ir.FilterStringOp, Src: "\"[$_]$_\"", Value: "[$_]$_"}}, }, }, }, { Line: 63, Op: ir.FilterGtEqOp, Src: "m[\"x\"].Type.Size >= 256", Args: []ir.FilterExpr{ { Line: 63, Op: ir.FilterVarTypeSizeOp, Src: "m[\"x\"].Type.Size", Value: "x", }, { Line: 63, Op: ir.FilterIntOp, Src: "256", Value: int64(256), }, }, }, }, }, LocationVar: "x", }}, }, { Line: 72, Name: "rangeExprCopy", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Detects big array copy in loop", DocBefore: "for _, x := range xs { myfunc(x) } // var xs [2048]string", DocAfter: "for _, x := range &xs { myfunc(x) }", Rules: []ir.Rule{{ Line: 73, SyntaxPatterns: []ir.PatternString{ {Line: 73, Value: "for $_, $_ := range $x { $*_ }"}, {Line: 74, Value: "for $_, $_ = range $x { $*_ }"}, }, ReportTemplate: "copy of $x can be avoided with &$x", SuggestTemplate: "&$x", WhereExpr: ir.FilterExpr{ Line: 75, Op: ir.FilterAndOp, Src: "m[\"x\"].Type.Is(\"[$_]$_\") && m[\"x\"].Type.Size >= 256", Args: []ir.FilterExpr{ { Line: 75, Op: ir.FilterVarTypeIsOp, Src: "m[\"x\"].Type.Is(\"[$_]$_\")", Value: "x", Args: []ir.FilterExpr{{Line: 75, Op: ir.FilterStringOp, Src: "\"[$_]$_\"", Value: "[$_]$_"}}, }, { Line: 75, Op: ir.FilterGtEqOp, Src: "m[\"x\"].Type.Size >= 256", Args: []ir.FilterExpr{ { Line: 75, Op: ir.FilterVarTypeSizeOp, Src: "m[\"x\"].Type.Size", Value: "x", }, { Line: 75, Op: ir.FilterIntOp, Src: "256", Value: int64(256), }, }, }, }, }, LocationVar: "x", }}, }, { Line: 83, Name: "ifacePtr", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Detects pointer to interface{}", Rules: []ir.Rule{{ Line: 84, SyntaxPatterns: []ir.PatternString{{Line: 84, Value: "*$x"}}, ReportTemplate: "don't use pointers to an interface", WhereExpr: ir.FilterExpr{ Line: 85, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(`interface{ $*_ }`)", Value: "x", Args: []ir.FilterExpr{{Line: 85, Op: ir.FilterStringOp, Src: "`interface{ $*_ }`", Value: "interface{ $*_ }"}}, }, }}, }, { Line: 93, Name: "camelCaseNaming", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects non camel case naming strategy for functions, constants, types, variables", DocBefore: "type my_type struct {}", DocAfter: "type myType struct {}", Rules: []ir.Rule{{ Line: 94, SyntaxPatterns: []ir.PatternString{ {Line: 95, Value: "func $x($*_) $*_ { $*_ }"}, {Line: 96, Value: "func ($_) $x($*_) $*_ { $*_ }"}, {Line: 97, Value: "func ($_ $_) $x($*_) $*_ { $*_ }"}, {Line: 98, Value: "const $x = $_"}, {Line: 98, Value: "const $x $_ = $_"}, {Line: 99, Value: "const ($x = $_; $*_)"}, {Line: 100, Value: "const ($_ = $_; $x = $_; $*_)"}, {Line: 101, Value: "const ($x $_= $_; $*_)"}, {Line: 102, Value: "const ($_ $_ = $_; $x $_= $_; $*_)"}, {Line: 103, Value: "type $x $_"}, {Line: 104, Value: "$x := $_"}, {Line: 105, Value: "var $x = $_"}, {Line: 106, Value: "var $x $_ = $_"}, }, ReportTemplate: "use camelCase naming strategy", WhereExpr: ir.FilterExpr{ Line: 108, Op: ir.FilterAndOp, Src: "!m[\"x\"].Text.Matches(`^_$`) && (m[\"x\"].Text.Matches(`-|_`))", Args: []ir.FilterExpr{ { Line: 108, Op: ir.FilterNotOp, Src: "!m[\"x\"].Text.Matches(`^_$`)", Args: []ir.FilterExpr{{ Line: 108, Op: ir.FilterVarTextMatchesOp, Src: "m[\"x\"].Text.Matches(`^_$`)", Value: "x", Args: []ir.FilterExpr{{Line: 108, Op: ir.FilterStringOp, Src: "`^_$`", Value: "^_$"}}, }}, }, { Line: 108, Op: ir.FilterVarTextMatchesOp, Src: "(m[\"x\"].Text.Matches(`-|_`))", Value: "x", Args: []ir.FilterExpr{{Line: 108, Op: ir.FilterStringOp, Src: "`-|_`", Value: "-|_"}}, }, }, }, LocationVar: "x", }}, }, { Line: 117, Name: "notInformativePackageNaming", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects general names for package", DocBefore: "package lib", DocAfter: "package concreteLib", Rules: []ir.Rule{{ Line: 118, SyntaxPatterns: []ir.PatternString{{Line: 118, Value: "package $x"}}, ReportTemplate: "don't use general names to package naming", WhereExpr: ir.FilterExpr{ Line: 119, Op: ir.FilterOrOp, Src: "m[\"x\"].Text.Matches(`(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^l|L|_(l|L))ib([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^u|U|_(u|U))til([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^s|S|_(s|S))hared([A-Z]|_|$|\\d)`)", Args: []ir.FilterExpr{ { Line: 119, Op: ir.FilterOrOp, Src: "m[\"x\"].Text.Matches(`(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^l|L|_(l|L))ib([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^u|U|_(u|U))til([A-Z]|_|$|\\d)`)", Args: []ir.FilterExpr{ { Line: 119, Op: ir.FilterOrOp, Src: "m[\"x\"].Text.Matches(`(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)`) ||\n\tm[\"x\"].Text.Matches(`(^l|L|_(l|L))ib([A-Z]|_|$|\\d)`)", Args: []ir.FilterExpr{ { Line: 119, Op: ir.FilterVarTextMatchesOp, Src: "m[\"x\"].Text.Matches(`(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)`)", Value: "x", Args: []ir.FilterExpr{{Line: 119, Op: ir.FilterStringOp, Src: "`(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)`", Value: "(^c|C|_(c|C))ommon([A-Z]|_|$|\\d)"}}, }, { Line: 120, Op: ir.FilterVarTextMatchesOp, Src: "m[\"x\"].Text.Matches(`(^l|L|_(l|L))ib([A-Z]|_|$|\\d)`)", Value: "x", Args: []ir.FilterExpr{{Line: 120, Op: ir.FilterStringOp, Src: "`(^l|L|_(l|L))ib([A-Z]|_|$|\\d)`", Value: "(^l|L|_(l|L))ib([A-Z]|_|$|\\d)"}}, }, }, }, { Line: 121, Op: ir.FilterVarTextMatchesOp, Src: "m[\"x\"].Text.Matches(`(^u|U|_(u|U))til([A-Z]|_|$|\\d)`)", Value: "x", Args: []ir.FilterExpr{{Line: 121, Op: ir.FilterStringOp, Src: "`(^u|U|_(u|U))til([A-Z]|_|$|\\d)`", Value: "(^u|U|_(u|U))til([A-Z]|_|$|\\d)"}}, }, }, }, { Line: 122, Op: ir.FilterVarTextMatchesOp, Src: "m[\"x\"].Text.Matches(`(^s|S|_(s|S))hared([A-Z]|_|$|\\d)`)", Value: "x", Args: []ir.FilterExpr{{Line: 122, Op: ir.FilterStringOp, Src: "`(^s|S|_(s|S))hared([A-Z]|_|$|\\d)`", Value: "(^s|S|_(s|S))hared([A-Z]|_|$|\\d)"}}, }, }, }, LocationVar: "x", }}, }, { Line: 131, Name: "getterNaming", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects 'get' word in getter functions", DocBefore: "func (x myType) getValue() string { return x.v }", DocAfter: "func (x myType) value() string { return x.v }", Rules: []ir.Rule{{ Line: 132, SyntaxPatterns: []ir.PatternString{ {Line: 133, Value: "func ($x $_) $name($*_) $*_ { return $x.$_ }"}, {Line: 134, Value: "func ($x $_) $name($*_) $*_ { return $_($x.$_) }"}, {Line: 135, Value: "func ($x $_) $name($*_) $*_ { return $_($x) }"}, {Line: 136, Value: "func ($x $_) $name($*_) $*_ { return $_(*$x) }"}, }, ReportTemplate: "don't use 'get' in getter functions", WhereExpr: ir.FilterExpr{ Line: 138, Op: ir.FilterVarTextMatchesOp, Src: "m[\"name\"].Text.Matches(`(^g|G|_(g|G))et([A-Z]|$|_|\\d)`)", Value: "name", Args: []ir.FilterExpr{{Line: 138, Op: ir.FilterStringOp, Src: "`(^g|G|_(g|G))et([A-Z]|$|_|\\d)`", Value: "(^g|G|_(g|G))et([A-Z]|$|_|\\d)"}}, }, LocationVar: "name", }}, }, { Line: 155, Name: "interfaceWordInInterfaceDeclaration", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects 'interface' word in interface declarations", DocBefore: "type interfaceDb interface { }", DocAfter: "type db interface { }", Rules: []ir.Rule{{ Line: 156, SyntaxPatterns: []ir.PatternString{{Line: 156, Value: "type $name interface{ $*_ }"}}, ReportTemplate: "don't use 'interface' word' in interface declaration'", WhereExpr: ir.FilterExpr{ Line: 157, Op: ir.FilterVarTextMatchesOp, Src: "m[\"name\"].Text.Matches(`(^i|I|_(i|I))nterface([A-Z]|_|$|\\d)`)", Value: "name", Args: []ir.FilterExpr{{Line: 157, Op: ir.FilterStringOp, Src: "`(^i|I|_(i|I))nterface([A-Z]|_|$|\\d)`", Value: "(^i|I|_(i|I))nterface([A-Z]|_|$|\\d)"}}, }, LocationVar: "name", }}, }, { Line: 168, Name: "simplifyErrorReturn", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects expressions that can be rewritten in form without 'if' usage", DocBefore: "err := myFunc(); if err != nil { return err }; return nil", DocAfter: "return myFunc()", Rules: []ir.Rule{{ Line: 169, SyntaxPatterns: []ir.PatternString{ {Line: 169, Value: "if $*_, $err = $_; $err != nil { return $err }; return nil"}, {Line: 170, Value: "if $*_, $err := $_; $err != nil { return $err }; return nil"}, {Line: 171, Value: "$*_, $err = $_; if $err != nil { return $err }; return nil"}, {Line: 172, Value: "var $*_, $err = $_; if $err != nil { return $err }; return nil"}, {Line: 173, Value: "$*_, $err := $_; if $err != nil { return $err }; return nil"}, {Line: 174, Value: "if $*_, $err = $_; $err != nil { return $err }; return $err"}, {Line: 175, Value: "if $*_, $err := $_; $err != nil { return $err }; return $err"}, {Line: 176, Value: "$*_, $err = $_; if $err != nil { return $err }; return $err"}, {Line: 177, Value: "var $*_, $err = $_; if $err != nil { return $err }; return $err"}, {Line: 178, Value: "$*_, $err := $_; if $err != nil { return $err }; return $err"}, }, ReportTemplate: "may be simplified to return error without if statement", WhereExpr: ir.FilterExpr{ Line: 180, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(\"error\")", Value: "err", Args: []ir.FilterExpr{{Line: 180, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, }}, }, { Line: 238, Name: "deferInLoop", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Detects loops inside functions that use defer", DocBefore: "for _, filename := range []string{\"foo\", \"bar\"} { f, err := os.Open(filename); defer f.Close() }", DocAfter: "func process(filename string) {", Rules: []ir.Rule{{ Line: 239, SyntaxPatterns: []ir.PatternString{ {Line: 240, Value: "for $*_; $*_; $*_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 241, Value: "for $*_; $*_; $*_ { $*_; defer $_($*args); $*_ }"}, {Line: 243, Value: "for { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 244, Value: "for { $*_; defer $_($*args); $*_ }"}, {Line: 246, Value: "for $_, $_ := range $_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 247, Value: "for $_, $_ := range $_ { $*_; defer $_($*args); $*_ }"}, {Line: 249, Value: "for $_, $_ = range $_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 250, Value: "for $_, $_ = range $_ { $*_; defer $_($*args); $*_ }"}, {Line: 252, Value: "for $_ := range $_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 253, Value: "for $_ := range $_ { $*_; defer $_($*args); $*_ }"}, {Line: 255, Value: "for $_ = range $_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 256, Value: "for $_ = range $_ { $*_; defer $_($*args); $*_ }"}, {Line: 258, Value: "for range $_ { $*_; defer func($*args) $*_ { $*_ }($*_); $*_ }"}, {Line: 259, Value: "for range $_ { $*_; defer $_($*args); $*_ }"}, }, ReportTemplate: "Possible resource leak, 'defer' is called in the 'for' loop", LocationVar: "args", }}, }, { Line: 312, Name: "regexpCompileInLoop", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Detects regular expression compilation in loop", DocBefore: "for { if regexp.MatchString(\"\\d\", \"123\") { /*...*/ } }", DocAfter: "dig := regexp.MustCompile(\"\\d\"); for { if dig.MatchString(\"123\") { /*...*/ } }", Rules: []ir.Rule{{ Line: 313, SyntaxPatterns: []ir.PatternString{ {Line: 314, Value: "for $*_; $*_; $*_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 315, Value: "for { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 316, Value: "for $_, $_ := range $_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 317, Value: "for $_, $_ = range $_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 318, Value: "for $_ := range $_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 319, Value: "for $_ = range $_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 320, Value: "for range $_ { $*_; $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 322, Value: "for $*_; $*_; $*_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 323, Value: "for { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 324, Value: "for $_, $_ := range $_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 325, Value: "for $_, $_ = range $_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 326, Value: "for $_ := range $_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 327, Value: "for $_ = range $_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 328, Value: "for range $_ { $*_; $*_ := regexp.$method($s, $*args); $*_ }"}, {Line: 330, Value: "for $*_; $*_; $*_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 331, Value: "for { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 332, Value: "for $_, $_ := range $_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 333, Value: "for $_, $_ = range $_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 334, Value: "for $_ := range $_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 335, Value: "for $_ = range $_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, {Line: 336, Value: "for range $_ { $*_; var $*_ $*_ = regexp.$method($s, $*args); $*_ }"}, }, ReportTemplate: "don't compile regex in the loop, move it outside of the loop", WhereExpr: ir.FilterExpr{ Line: 339, Op: ir.FilterAndOp, Src: "m[\"s\"].Const && !m[\"method\"].Contains(`QuoteMeta`)", Args: []ir.FilterExpr{ { Line: 339, Op: ir.FilterVarConstOp, Src: "m[\"s\"].Const", Value: "s", }, { Line: 339, Op: ir.FilterNotOp, Src: "!m[\"method\"].Contains(`QuoteMeta`)", Args: []ir.FilterExpr{{ Line: 339, Op: ir.FilterVarContainsOp, Src: "m[\"method\"].Contains(`QuoteMeta`)", Value: "method", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "QuoteMeta"}}, }}, }, }, }, LocationVar: "s", }}, }, { Line: 347, Name: "unclosedResource", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Detects unreleased resources", DocBefore: "s, _ := os.Open(\"foo.txt\"); s.Read(body); return body", DocAfter: "s, _ := os.Open(\"foo.txt\"); defer s.Close(); s.Read(body); return body", Rules: []ir.Rule{{ Line: 356, SyntaxPatterns: []ir.PatternString{ {Line: 356, Value: "$res, $err := $_($*_); $*body"}, {Line: 357, Value: "$res, $err = $_($*_); $*body"}, {Line: 358, Value: "var $res, $err = $_($*_); $*body"}, }, ReportTemplate: "$res.Close() should be deferred right after the resource creation", WhereExpr: ir.FilterExpr{ Line: 361, Op: ir.FilterAndOp, Src: "m[\"res\"].Type.Implements(`io.Closer`) &&\n\t!m[\"res\"].Object.IsGlobal() &&\n\tm[\"err\"].Type.Implements(`error`) &&\n\t!m[\"body\"].Contains(`$res.Close()`) &&\n\t!varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 361, Op: ir.FilterAndOp, Src: "m[\"res\"].Type.Implements(`io.Closer`) &&\n\t!m[\"res\"].Object.IsGlobal() &&\n\tm[\"err\"].Type.Implements(`error`) &&\n\t!m[\"body\"].Contains(`$res.Close()`)", Args: []ir.FilterExpr{ { Line: 361, Op: ir.FilterAndOp, Src: "m[\"res\"].Type.Implements(`io.Closer`) &&\n\t!m[\"res\"].Object.IsGlobal() &&\n\tm[\"err\"].Type.Implements(`error`)", Args: []ir.FilterExpr{ { Line: 361, Op: ir.FilterAndOp, Src: "m[\"res\"].Type.Implements(`io.Closer`) &&\n\t!m[\"res\"].Object.IsGlobal()", Args: []ir.FilterExpr{ { Line: 361, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"res\"].Type.Implements(`io.Closer`)", Value: "res", Args: []ir.FilterExpr{{Line: 361, Op: ir.FilterStringOp, Src: "`io.Closer`", Value: "io.Closer"}}, }, { Line: 362, Op: ir.FilterNotOp, Src: "!m[\"res\"].Object.IsGlobal()", Args: []ir.FilterExpr{{ Line: 362, Op: ir.FilterVarObjectIsGlobalOp, Src: "m[\"res\"].Object.IsGlobal()", Value: "res", }}, }, }, }, { Line: 363, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(`error`)", Value: "err", Args: []ir.FilterExpr{{Line: 363, Op: ir.FilterStringOp, Src: "`error`", Value: "error"}}, }, }, }, { Line: 364, Op: ir.FilterNotOp, Src: "!m[\"body\"].Contains(`$res.Close()`)", Args: []ir.FilterExpr{{ Line: 364, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$res.Close()`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$res.Close()"}}, }}, }, }, }, { Line: 365, Op: ir.FilterNotOp, Src: "!varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{{ Line: 365, Op: ir.FilterOrOp, Src: "varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $res`) ||\n\n\tm[\"body\"].Contains(`$_[$res] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $res;`) ||\n\n\tm[\"body\"].Contains(`$_ := $res;`) ||\n\n\tm[\"body\"].Contains(`var $_ = $res;`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $res`) ||\n\n\tm[\"body\"].Contains(`$_[$res] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $res;`) ||\n\n\tm[\"body\"].Contains(`$_ := $res;`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $res`) ||\n\n\tm[\"body\"].Contains(`$_[$res] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $res;`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $res`) ||\n\n\tm[\"body\"].Contains(`$_[$res] = $_`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $res`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`) ||\n\n\tm[\"body\"].Contains(`return $*_, $res, $*_`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $res`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`)", Args: []ir.FilterExpr{ { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $res, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $res, $*_}"}}, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $_: $res, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $_: $res, $*_}"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ <- $res`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ <- $res"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`return $*_, $res, $*_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "return $*_, $res, $*_"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$_] = $res`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$_] = $res"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$res] = $_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$res] = $_"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ = $res;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ = $res;"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ := $res;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ := $res;"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ = $res;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ = $res;"}}, }, }, }, { Line: 365, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ $_ = $res;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ $_ = $res;"}}, }, }, }}, }, }, }, LocationVar: "res", }}, }, { Line: 375, Name: "unstoppedTimer", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Detects unreleased timer", DocBefore: "timer := time.NewTimer(time.Second); select { case <-timer.C: return nil; default: return nil }", DocAfter: "timer := time.NewTimer(time.Second); defer timer.Stop(); select { case <-timer.C: return nil; default: return nil }", Rules: []ir.Rule{{ Line: 384, SyntaxPatterns: []ir.PatternString{ {Line: 384, Value: "$x := time.NewTimer($_); $*body"}, {Line: 385, Value: "$x = time.NewTimer($_); $*body"}, {Line: 386, Value: "var $x = time.NewTimer($_); $*body"}, {Line: 387, Value: "var $x $_ = time.NewTimer($_); $*body"}, }, ReportTemplate: "unstopped timer", WhereExpr: ir.FilterExpr{ Line: 388, Op: ir.FilterAndOp, Src: "!m[\"x\"].Object.IsGlobal() && !m[\"body\"].Contains(`$x.Stop()`) && !varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterAndOp, Src: "!m[\"x\"].Object.IsGlobal() && !m[\"body\"].Contains(`$x.Stop()`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterNotOp, Src: "!m[\"x\"].Object.IsGlobal()", Args: []ir.FilterExpr{{ Line: 388, Op: ir.FilterVarObjectIsGlobalOp, Src: "m[\"x\"].Object.IsGlobal()", Value: "x", }}, }, { Line: 388, Op: ir.FilterNotOp, Src: "!m[\"body\"].Contains(`$x.Stop()`)", Args: []ir.FilterExpr{{ Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$x.Stop()`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$x.Stop()"}}, }}, }, }, }, { Line: 388, Op: ir.FilterNotOp, Src: "!varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{{ Line: 388, Op: ir.FilterOrOp, Src: "varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`) ||\n\n\tm[\"body\"].Contains(`$_ := $x;`) ||\n\n\tm[\"body\"].Contains(`var $_ = $x;`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`) ||\n\n\tm[\"body\"].Contains(`$_ := $x;`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`)", Args: []ir.FilterExpr{ { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_($*_, $x, $*_)"}}, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $x, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $x, $*_}"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $_: $x, $*_}"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ <- $x`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ <- $x"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`return $*_, $x, $*_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "return $*_, $x, $*_"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$_] = $x`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$_] = $x"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$x] = $_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$x] = $_"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ = $x;"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ := $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ := $x;"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ = $x;"}}, }, }, }, { Line: 388, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ $_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ $_ = $x;"}}, }, }, }}, }, }, }, LocationVar: "x", }}, }, { Line: 397, Name: "unstoppedTicker", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Detects unreleased ticker", DocBefore: "ticker := time.NewTicker(time.Second); select { case <-ticker.C: return nil; default: return nil }", DocAfter: "ticker := time.NewTicker(time.Second); defer ticker.Stop(); select { case <-ticker.C: return nil; default: return nil }", Rules: []ir.Rule{{ Line: 406, SyntaxPatterns: []ir.PatternString{ {Line: 406, Value: "$x := time.NewTicker($_); $*body"}, {Line: 407, Value: "$x = time.NewTicker($_); $*body"}, {Line: 408, Value: "var $x = time.NewTicker($_); $*body"}, {Line: 409, Value: "var $x $_ = time.NewTicker($_); $*body"}, }, ReportTemplate: "unstopped ticker", WhereExpr: ir.FilterExpr{ Line: 410, Op: ir.FilterAndOp, Src: "!m[\"x\"].Object.IsGlobal() && !m[\"body\"].Contains(`$x.Stop()`) && !varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterAndOp, Src: "!m[\"x\"].Object.IsGlobal() && !m[\"body\"].Contains(`$x.Stop()`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterNotOp, Src: "!m[\"x\"].Object.IsGlobal()", Args: []ir.FilterExpr{{ Line: 410, Op: ir.FilterVarObjectIsGlobalOp, Src: "m[\"x\"].Object.IsGlobal()", Value: "x", }}, }, { Line: 410, Op: ir.FilterNotOp, Src: "!m[\"body\"].Contains(`$x.Stop()`)", Args: []ir.FilterExpr{{ Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$x.Stop()`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$x.Stop()"}}, }}, }, }, }, { Line: 410, Op: ir.FilterNotOp, Src: "!varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{{ Line: 410, Op: ir.FilterOrOp, Src: "varEscapeFunction(m[\"body\"])", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`) ||\n\n\tm[\"body\"].Contains(`$_ := $x;`) ||\n\n\tm[\"body\"].Contains(`var $_ = $x;`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`) ||\n\n\tm[\"body\"].Contains(`$_ := $x;`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`) ||\n\n\tm[\"body\"].Contains(`$_ = $x;`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`) ||\n\n\tm[\"body\"].Contains(`$_[$x] = $_`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`) ||\n\n\tm[\"body\"].Contains(`$_[$_] = $x`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`) ||\n\n\tm[\"body\"].Contains(`return $*_, $x, $*_`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_ <- $x`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterOrOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`) ||\n\n\tm[\"body\"].Contains(`$_{$*_, $x, $*_}`)", Args: []ir.FilterExpr{ { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_($*_, $x, $*_)`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_($*_, $x, $*_)"}}, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $x, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $x, $*_}"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_{$*_, $_: $x, $*_}`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_{$*_, $_: $x, $*_}"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ <- $x`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ <- $x"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`return $*_, $x, $*_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "return $*_, $x, $*_"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$_] = $x`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$_] = $x"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_[$x] = $_`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_[$x] = $_"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ = $x;"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$_ := $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$_ := $x;"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ = $x;"}}, }, }, }, { Line: 410, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`var $_ $_ = $x;`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "var $_ $_ = $x;"}}, }, }, }}, }, }, }, LocationVar: "x", }}, }, { Line: 419, Name: "simplifyErrorCheck", MatcherName: "m", DocTags: []string{"style"}, DocSummary: "Detects expressions that can be rewritten in one 'if' form", DocBefore: "err := myFunc(); if err != nil { println(err) }", DocAfter: "if err := myFunc(); err != nil { println(err) }", Rules: []ir.Rule{ { Line: 420, SyntaxPatterns: []ir.PatternString{{Line: 420, Value: "$err := $f($*args); if $err != nil { $*body }"}}, ReportTemplate: "error check can be simplified in one line", SuggestTemplate: "if $err := $f($args); $err != nil { $body }", WhereExpr: ir.FilterExpr{ Line: 421, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\") && m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 421, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 421, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(\"error\")", Value: "err", Args: []ir.FilterExpr{{Line: 421, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, { Line: 422, Op: ir.FilterVarTextMatchesOp, Src: "m[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "f", Args: []ir.FilterExpr{{Line: 422, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, { Line: 422, Op: ir.FilterVarTextMatchesOp, Src: "m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "args", Args: []ir.FilterExpr{{Line: 422, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, }, { Line: 426, SyntaxPatterns: []ir.PatternString{{Line: 426, Value: "$err = $f($*args); if $err != nil { $*body }"}}, ReportTemplate: "error check can be simplified in one line", SuggestTemplate: "if $err = $f($args); $err != nil { $body }", WhereExpr: ir.FilterExpr{ Line: 427, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\") && m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 427, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 427, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(\"error\")", Value: "err", Args: []ir.FilterExpr{{Line: 427, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, { Line: 428, Op: ir.FilterVarTextMatchesOp, Src: "m[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "f", Args: []ir.FilterExpr{{Line: 428, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, { Line: 428, Op: ir.FilterVarTextMatchesOp, Src: "m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "args", Args: []ir.FilterExpr{{Line: 428, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, }, { Line: 432, SyntaxPatterns: []ir.PatternString{{Line: 432, Value: "var $err = $f($*args); if $err != nil { $*body }"}}, ReportTemplate: "error check can be simplified in one line", SuggestTemplate: "if $err := $f($args); $err != nil { $body }", WhereExpr: ir.FilterExpr{ Line: 433, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\") && m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 433, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") &&\n\tm[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Args: []ir.FilterExpr{ { Line: 433, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(\"error\")", Value: "err", Args: []ir.FilterExpr{{Line: 433, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, { Line: 434, Op: ir.FilterVarTextMatchesOp, Src: "m[\"f\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "f", Args: []ir.FilterExpr{{Line: 434, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, { Line: 434, Op: ir.FilterVarTextMatchesOp, Src: "m[\"args\"].Text.Matches(\"(?s)^.{0,40}$\")", Value: "args", Args: []ir.FilterExpr{{Line: 434, Op: ir.FilterStringOp, Src: "\"(?s)^.{0,40}$\"", Value: "(?s)^.{0,40}$"}}, }, }, }, }, }, }, { Line: 441, Name: "syncPoolNonPtr", MatcherName: "m", DocTags: []string{"performance"}, DocSummary: "Non-pointer values in sync.Pool involve extra allocation", Rules: []ir.Rule{{ Line: 448, SyntaxPatterns: []ir.PatternString{{Line: 448, Value: "$x.Put($y)"}}, ReportTemplate: "non-pointer values in sync.Pool involve extra allocation", WhereExpr: ir.FilterExpr{ Line: 449, Op: ir.FilterAndOp, Src: "m[\"x\"].Type.Is(\"sync.Pool\") && !isPointer(m[\"y\"])", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterVarTypeIsOp, Src: "m[\"x\"].Type.Is(\"sync.Pool\")", Value: "x", Args: []ir.FilterExpr{{Line: 449, Op: ir.FilterStringOp, Src: "\"sync.Pool\"", Value: "sync.Pool"}}, }, { Line: 449, Op: ir.FilterNotOp, Src: "!isPointer(m[\"y\"])", Args: []ir.FilterExpr{{ Line: 449, Op: ir.FilterOrOp, Src: "isPointer(m[\"y\"])", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterOrOp, Src: "m[\"y\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"map[$_]$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"interface{$*_}\") ||\n\n\tm[\"y\"].Type.Underlying().Is(`func($*_) $*_`)", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterOrOp, Src: "m[\"y\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"map[$_]$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"interface{$*_}\")", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterOrOp, Src: "m[\"y\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"map[$_]$_\")", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterOrOp, Src: "m[\"y\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"y\"].Type.Underlying().Is(\"chan $_\")", Args: []ir.FilterExpr{ { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(\"*$_\")", Value: "y", Args: []ir.FilterExpr{{Line: 443, Op: ir.FilterStringOp, Src: "\"*$_\"", Value: "*$_"}}, }, { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(\"chan $_\")", Value: "y", Args: []ir.FilterExpr{{Line: 443, Op: ir.FilterStringOp, Src: "\"chan $_\"", Value: "chan $_"}}, }, }, }, { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(\"map[$_]$_\")", Value: "y", Args: []ir.FilterExpr{{Line: 444, Op: ir.FilterStringOp, Src: "\"map[$_]$_\"", Value: "map[$_]$_"}}, }, }, }, { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(\"interface{$*_}\")", Value: "y", Args: []ir.FilterExpr{{Line: 444, Op: ir.FilterStringOp, Src: "\"interface{$*_}\"", Value: "interface{$*_}"}}, }, }, }, { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(`func($*_) $*_`)", Value: "y", Args: []ir.FilterExpr{{Line: 445, Op: ir.FilterStringOp, Src: "`func($*_) $*_`", Value: "func($*_) $*_"}}, }, }, }, { Line: 449, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"y\"].Type.Underlying().Is(`unsafe.Pointer`)", Value: "y", Args: []ir.FilterExpr{{Line: 445, Op: ir.FilterStringOp, Src: "`unsafe.Pointer`", Value: "unsafe.Pointer"}}, }, }, }}, }, }, }, LocationVar: "y", }}, }, { Line: 456, Name: "uselessLocalConst", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Detects useless local constants", Rules: []ir.Rule{{ Line: 457, SyntaxPatterns: []ir.PatternString{ {Line: 457, Value: "const $x = $_; $*body"}, {Line: 457, Value: "const $x $_ = $_; $*body"}, }, ReportTemplate: "useless local constant", WhereExpr: ir.FilterExpr{ Line: 458, Op: ir.FilterAndOp, Src: "!m[\"x\"].Object.IsGlobal() && !m[\"body\"].Contains(`$x`)", Args: []ir.FilterExpr{ { Line: 458, Op: ir.FilterNotOp, Src: "!m[\"x\"].Object.IsGlobal()", Args: []ir.FilterExpr{{ Line: 458, Op: ir.FilterVarObjectIsGlobalOp, Src: "m[\"x\"].Object.IsGlobal()", Value: "x", }}, }, { Line: 458, Op: ir.FilterNotOp, Src: "!m[\"body\"].Contains(`$x`)", Args: []ir.FilterExpr{{ Line: 458, Op: ir.FilterVarContainsOp, Src: "m[\"body\"].Contains(`$x`)", Value: "body", Args: []ir.FilterExpr{{Line: 0, Op: ir.FilterStringOp, Src: "", Value: "$x"}}, }}, }, }, }, }}, }, { Line: 464, Name: "oneLineReturn", MatcherName: "m", DocTags: []string{"style", "experimental"}, DocSummary: "Detects variables assigment before return that can be simplified", Rules: []ir.Rule{{ Line: 471, SyntaxPatterns: []ir.PatternString{ {Line: 472, Value: "var $x = $v; return $x"}, {Line: 473, Value: "$x := $v; return $x"}, }, ReportTemplate: "suggestion: return $v", SuggestTemplate: "return $v", WhereExpr: ir.FilterExpr{ Line: 475, Op: ir.FilterNotOp, Src: "!isPointer(m[\"x\"])", Args: []ir.FilterExpr{{ Line: 475, Op: ir.FilterOrOp, Src: "isPointer(m[\"x\"])", Args: []ir.FilterExpr{ { Line: 475, Op: ir.FilterOrOp, Src: "m[\"x\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"map[$_]$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"interface{$*_}\") ||\n\n\tm[\"x\"].Type.Underlying().Is(`func($*_) $*_`)", Args: []ir.FilterExpr{ { Line: 475, Op: ir.FilterOrOp, Src: "m[\"x\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"map[$_]$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"interface{$*_}\")", Args: []ir.FilterExpr{ { Line: 475, Op: ir.FilterOrOp, Src: "m[\"x\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"chan $_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"map[$_]$_\")", Args: []ir.FilterExpr{ { Line: 475, Op: ir.FilterOrOp, Src: "m[\"x\"].Type.Underlying().Is(\"*$_\") ||\n\n\tm[\"x\"].Type.Underlying().Is(\"chan $_\")", Args: []ir.FilterExpr{ { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(\"*$_\")", Value: "x", Args: []ir.FilterExpr{{Line: 466, Op: ir.FilterStringOp, Src: "\"*$_\"", Value: "*$_"}}, }, { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(\"chan $_\")", Value: "x", Args: []ir.FilterExpr{{Line: 466, Op: ir.FilterStringOp, Src: "\"chan $_\"", Value: "chan $_"}}, }, }, }, { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(\"map[$_]$_\")", Value: "x", Args: []ir.FilterExpr{{Line: 467, Op: ir.FilterStringOp, Src: "\"map[$_]$_\"", Value: "map[$_]$_"}}, }, }, }, { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(\"interface{$*_}\")", Value: "x", Args: []ir.FilterExpr{{Line: 467, Op: ir.FilterStringOp, Src: "\"interface{$*_}\"", Value: "interface{$*_}"}}, }, }, }, { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(`func($*_) $*_`)", Value: "x", Args: []ir.FilterExpr{{Line: 468, Op: ir.FilterStringOp, Src: "`func($*_) $*_`", Value: "func($*_) $*_"}}, }, }, }, { Line: 475, Op: ir.FilterVarTypeUnderlyingIsOp, Src: "m[\"x\"].Type.Underlying().Is(`unsafe.Pointer`)", Value: "x", Args: []ir.FilterExpr{{Line: 468, Op: ir.FilterStringOp, Src: "`unsafe.Pointer`", Value: "unsafe.Pointer"}}, }, }, }}, }, }}, }, { Line: 492, Name: "errCheckInIf", MatcherName: "m", DocTags: []string{"diagnostic"}, DocSummary: "Finds unchecked errors in if statements", DocBefore: "if err := expr(); err2 != nil { /*...*/ }", DocAfter: "if err := expr(); err != nil { /*...*/ }", Rules: []ir.Rule{{ Line: 493, SyntaxPatterns: []ir.PatternString{ {Line: 494, Value: "if $err := $_($*_); $err2 != nil { $*_ }"}, {Line: 495, Value: "if $err = $_($*_); $err2 != nil { $*_ }"}, {Line: 496, Value: "if $*_, $err := $_($*_); $err2 != nil { $*_ }"}, {Line: 497, Value: "if $*_, $err = $_($*_); $err2 != nil { $*_ }"}, }, ReportTemplate: "returned error '$err' must be checked", WhereExpr: ir.FilterExpr{ Line: 498, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\") &&\n\tm[\"err\"].Text != m[\"err2\"].Text", Args: []ir.FilterExpr{ { Line: 498, Op: ir.FilterAndOp, Src: "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\")", Args: []ir.FilterExpr{ { Line: 498, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err\"].Type.Implements(\"error\")", Value: "err", Args: []ir.FilterExpr{{Line: 498, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, { Line: 498, Op: ir.FilterVarTypeImplementsOp, Src: "m[\"err2\"].Type.Implements(\"error\")", Value: "err2", Args: []ir.FilterExpr{{Line: 498, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}}, }, }, }, { Line: 499, Op: ir.FilterNeqOp, Src: "m[\"err\"].Text != m[\"err2\"].Text", Args: []ir.FilterExpr{ {Line: 499, Op: ir.FilterVarTextOp, Src: "m[\"err\"].Text", Value: "err"}, {Line: 499, Op: ir.FilterVarTextOp, Src: "m[\"err2\"].Text", Value: "err2"}, }, }, }, }, }}, }, }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.