Use binary version of revive linter (#15739)

Use the common `go get` method to install and run the revive linter,
removing the useless build/lint.go and related vendor libraries.
pull/15802/head
silverwind 2 years ago committed by GitHub
parent a69fb523a7
commit c3802dcc0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -282,7 +282,10 @@ errcheck:
.PHONY: revive
revive:
GO111MODULE=on $(GO) run -mod=vendor build/lint.go -config .revive.toml -exclude=./vendor/... ./... || exit 1
@hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
GO111MODULE=off $(GO) get -u github.com/mgechev/revive; \
fi
@revive -config .revive.toml -exclude=./vendor/... ./...
.PHONY: misspell-check
misspell-check:

@ -10,14 +10,6 @@ package main
// These libraries will not be included in a normal compilation.
import (
// for lint
_ "github.com/mgechev/dots"
_ "github.com/mgechev/revive/formatter"
_ "github.com/mgechev/revive/lint"
_ "github.com/mgechev/revive/rule"
_ "github.com/mitchellh/go-homedir"
_ "github.com/pelletier/go-toml"
// for embed
_ "github.com/shurcooL/vfsgen"

@ -1,325 +0,0 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Copyright (c) 2018 Minko Gechev. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// +build ignore
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/mgechev/dots"
"github.com/mgechev/revive/formatter"
"github.com/mgechev/revive/lint"
"github.com/mgechev/revive/rule"
"github.com/mitchellh/go-homedir"
"github.com/pelletier/go-toml"
)
func fail(err string) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
var defaultRules = []lint.Rule{
&rule.VarDeclarationsRule{},
&rule.PackageCommentsRule{},
&rule.DotImportsRule{},
&rule.BlankImportsRule{},
&rule.ExportedRule{},
&rule.VarNamingRule{},
&rule.IndentErrorFlowRule{},
&rule.IfReturnRule{},
&rule.RangeRule{},
&rule.ErrorfRule{},
&rule.ErrorNamingRule{},
&rule.ErrorStringsRule{},
&rule.ReceiverNamingRule{},
&rule.IncrementDecrementRule{},
&rule.ErrorReturnRule{},
&rule.UnexportedReturnRule{},
&rule.TimeNamingRule{},
&rule.ContextKeysType{},
&rule.ContextAsArgumentRule{},
}
var allRules = append([]lint.Rule{
&rule.ArgumentsLimitRule{},
&rule.CyclomaticRule{},
&rule.FileHeaderRule{},
&rule.EmptyBlockRule{},
&rule.SuperfluousElseRule{},
&rule.ConfusingNamingRule{},
&rule.GetReturnRule{},
&rule.ModifiesParamRule{},
&rule.ConfusingResultsRule{},
&rule.DeepExitRule{},
&rule.UnusedParamRule{},
&rule.UnreachableCodeRule{},
&rule.AddConstantRule{},
&rule.FlagParamRule{},
&rule.UnnecessaryStmtRule{},
&rule.StructTagRule{},
&rule.ModifiesValRecRule{},
&rule.ConstantLogicalExprRule{},
&rule.BoolLiteralRule{},
&rule.RedefinesBuiltinIDRule{},
&rule.ImportsBlacklistRule{},
&rule.FunctionResultsLimitRule{},
&rule.MaxPublicStructsRule{},
&rule.RangeValInClosureRule{},
&rule.RangeValAddress{},
&rule.WaitGroupByValueRule{},
&rule.AtomicRule{},
&rule.EmptyLinesRule{},
&rule.LineLengthLimitRule{},
&rule.CallToGCRule{},
&rule.DuplicatedImportsRule{},
&rule.ImportShadowingRule{},
&rule.BareReturnRule{},
&rule.UnusedReceiverRule{},
&rule.UnhandledErrorRule{},
&rule.CognitiveComplexityRule{},
&rule.StringOfIntRule{},
}, defaultRules...)
var allFormatters = []lint.Formatter{
&formatter.Stylish{},
&formatter.Friendly{},
&formatter.JSON{},
&formatter.NDJSON{},
&formatter.Default{},
&formatter.Unix{},
&formatter.Checkstyle{},
&formatter.Plain{},
}
func getFormatters() map[string]lint.Formatter {
result := map[string]lint.Formatter{}
for _, f := range allFormatters {
result[f.Name()] = f
}
return result
}
func getLintingRules(config *lint.Config) []lint.Rule {
rulesMap := map[string]lint.Rule{}
for _, r := range allRules {
rulesMap[r.Name()] = r
}
lintingRules := []lint.Rule{}
for name := range config.Rules {
rule, ok := rulesMap[name]
if !ok {
fail("cannot find rule: " + name)
}
lintingRules = append(lintingRules, rule)
}
return lintingRules
}
func parseConfig(path string) *lint.Config {
config := &lint.Config{}
file, err := ioutil.ReadFile(path)
if err != nil {
fail("cannot read the config file")
}
err = toml.Unmarshal(file, config)
if err != nil {
fail("cannot parse the config file: " + err.Error())
}
return config
}
func normalizeConfig(config *lint.Config) {
if config.Confidence == 0 {
config.Confidence = 0.8
}
severity := config.Severity
if severity != "" {
for k, v := range config.Rules {
if v.Severity == "" {
v.Severity = severity
}
config.Rules[k] = v
}
for k, v := range config.Directives {
if v.Severity == "" {
v.Severity = severity
}
config.Directives[k] = v
}
}
}
func getConfig() *lint.Config {
config := defaultConfig()
if configPath != "" {
config = parseConfig(configPath)
}
normalizeConfig(config)
return config
}
func getFormatter() lint.Formatter {
formatters := getFormatters()
formatter := formatters["default"]
if formatterName != "" {
f, ok := formatters[formatterName]
if !ok {
fail("unknown formatter " + formatterName)
}
formatter = f
}
return formatter
}
func buildDefaultConfigPath() string {
var result string
if homeDir, err := homedir.Dir(); err == nil {
result = filepath.Join(homeDir, "revive.toml")
if _, err := os.Stat(result); err != nil {
result = ""
}
}
return result
}
func defaultConfig() *lint.Config {
defaultConfig := lint.Config{
Confidence: 0.0,
Severity: lint.SeverityWarning,
Rules: map[string]lint.RuleConfig{},
}
for _, r := range defaultRules {
defaultConfig.Rules[r.Name()] = lint.RuleConfig{}
}
return &defaultConfig
}
func normalizeSplit(strs []string) []string {
res := []string{}
for _, s := range strs {
t := strings.Trim(s, " \t")
if len(t) > 0 {
res = append(res, t)
}
}
return res
}
func getPackages() [][]string {
globs := normalizeSplit(flag.Args())
if len(globs) == 0 {
globs = append(globs, ".")
}
packages, err := dots.ResolvePackages(globs, normalizeSplit(excludePaths))
if err != nil {
fail(err.Error())
}
return packages
}
type arrayFlags []string
func (i *arrayFlags) String() string {
return strings.Join([]string(*i), " ")
}
func (i *arrayFlags) Set(value string) error {
*i = append(*i, value)
return nil
}
var configPath string
var excludePaths arrayFlags
var formatterName string
var help bool
var originalUsage = flag.Usage
func init() {
flag.Usage = func() {
originalUsage()
}
// command line help strings
const (
configUsage = "path to the configuration TOML file, defaults to $HOME/revive.toml, if present (i.e. -config myconf.toml)"
excludeUsage = "list of globs which specify files to be excluded (i.e. -exclude foo/...)"
formatterUsage = "formatter to be used for the output (i.e. -formatter stylish)"
)
defaultConfigPath := buildDefaultConfigPath()
flag.StringVar(&configPath, "config", defaultConfigPath, configUsage)
flag.Var(&excludePaths, "exclude", excludeUsage)
flag.StringVar(&formatterName, "formatter", "", formatterUsage)
flag.Parse()
}
func main() {
config := getConfig()
formatter := getFormatter()
packages := getPackages()
revive := lint.New(func(file string) ([]byte, error) {
return ioutil.ReadFile(file)
})
lintingRules := getLintingRules(config)
failures, err := revive.Lint(packages, lintingRules, *config)
if err != nil {
fail(err.Error())
}
formatChan := make(chan lint.Failure)
exitChan := make(chan bool)
var output string
go (func() {
output, err = formatter.Format(formatChan, *config)
if err != nil {
fail(err.Error())
}
exitChan <- true
})()
exitCode := 0
for f := range failures {
if f.Confidence < config.Confidence {
continue
}
if exitCode == 0 {
exitCode = config.WarningCode
}
if c, ok := config.Rules[f.RuleName]; ok && c.Severity == lint.SeverityError {
exitCode = config.ErrorCode
}
if c, ok := config.Directives[f.RuleName]; ok && c.Severity == lint.SeverityError {
exitCode = config.ErrorCode
}
formatChan <- f
}
close(formatChan)
<-exitChan
if output != "" {
fmt.Println(output)
}
os.Exit(exitCode)
}

@ -22,7 +22,6 @@ require (
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/caddyserver/certmagic v0.13.0
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect
github.com/chi-middleware/proxy v1.1.1
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
github.com/couchbase/gomemcached v0.1.2 // indirect
@ -74,22 +73,20 @@ require (
github.com/mattn/go-isatty v0.0.12
github.com/mattn/go-runewidth v0.0.12 // indirect
github.com/mattn/go-sqlite3 v1.14.7
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81
github.com/mgechev/revive v1.0.6
github.com/mholt/archiver/v3 v3.5.0
github.com/microcosm-cc/bluemonday v1.0.8
github.com/miekg/dns v1.1.40 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.10
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/msteinert/pam v0.0.0-20201130170657-e61372126161
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/niklasfasching/go-org v1.5.0
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/oliamb/cutter v0.2.2
github.com/olivere/elastic/v7 v7.0.24
github.com/pelletier/go-toml v1.9.0
github.com/pelletier/go-toml v1.9.0 // indirect
github.com/pierrec/lz4/v4 v4.1.3 // indirect
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0

@ -196,9 +196,6 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chavacava/garif v0.0.0-20210405163807-87a70f3d418b/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU=
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI=
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU=
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -292,10 +289,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/ethantkoenig/rupture v1.0.0 h1:gPInt1N30UErGNzd8t5js5Qbnpjcd1l6yU2MCrJxIe8=
github.com/ethantkoenig/rupture v1.0.0/go.mod h1:GyE9QabHfxA6ch0NZgwsHopRbOLcYjUr9g4FTJmq0WM=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
@ -805,8 +798,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -825,10 +816,6 @@ github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEg
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM=
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
github.com/mgechev/revive v1.0.6 h1:MgRQ3ys2uQCyVjelaDhVs8oSvOPYInzGA/nNGMa+MNU=
github.com/mgechev/revive v1.0.6/go.mod h1:Lj5gIVxjBlH8REa3icEOkdfchwYc291nShzZ4QYWyMo=
github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk=
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE=

@ -1,3 +0,0 @@
*.test
*.out
.devcontainer/

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Salvador Cavadini
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.

@ -1,52 +0,0 @@
# garif
A GO package to create and manipulate SARIF logs.
SARIF, from _Static Analysis Results Interchange Format_, is a standard JSON-based format for the output of static analysis tools defined and promoted by [OASIS](https://www.oasis-open.org/).
Current supported version of the standard is [SARIF-v2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html
).
## Usage
The package provides access to every element of the SARIF model, therefore you are free to manipulate it at every detail.
The package also provides constructors functions (`New...`) and decorators methods (`With...`) that simplify the creation of SARIF files for common use cases.
Using these constructors and decorators we can easily create the example SARIF file of the [Microsoft SARIF pages](https://github.com/microsoft/sarif-tutorials/blob/master/docs/1-Introduction.md)
```go
import to `github.com/chavacava/garif`
// ...
rule := garif.NewRule("no-unused-vars").
WithHelpUri("https://eslint.org/docs/rules/no-unused-vars").
WithShortDescription("disallow unused variables").
WithProperties("category", "Variables")
driver := garif.NewDriver("ESLint").
WithInformationUri("https://eslint.org").
WithRules(rule)
run := garif.NewRun(NewTool(driver)).
WithArtifactsURIs("file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js")
run.WithResult(rule.Id, "'x' is assigned a value but never used.", "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js", 1, 5)
logFile := garif.NewLogFile([]*Run{run}, Version210)
logFile.Write(os.Stdout)
```
## Why this package?
This package was initiated during my works on adding to [`revive`](https://github.com/mgechev/revive) a SARIF output formatter.
I've tried to use [go-sarif](https://github.com/owenrumney/go-sarif) by [Owen Rumney](https://github.com/owenrumney) but it is too focused in the use case of the static analyzer [tfsec](https://tfsec.dev) so I've decided to create a package flexible enough to generate SARIF files in broader cases.
## More information about SARIF
For more information about SARIF, you can visit the [Oasis Open](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif) site.
## Contributing
Of course, contributions are welcome!

@ -1,338 +0,0 @@
package garif
// NewAddress creates a valid Address
func NewAddress() *Address {
return &Address{}
}
// NewArtifact creates a valid Artifact
func NewArtifact() *Artifact {
return &Artifact{}
}
// NewArtifactChange creates a valid ArtifactChange
func NewArtifactChange(location *ArtifactLocation, replacements ...*Replacement) *ArtifactChange {
return &ArtifactChange{
ArtifactLocation: location,
Replacements: replacements,
}
}
// NewArtifactContent creates a valid ArtifactContent
func NewArtifactContent() *ArtifactContent {
return &ArtifactContent{}
}
// NewArtifactLocation creates a valid ArtifactLocation
func NewArtifactLocation() *ArtifactLocation {
return &ArtifactLocation{}
}
// NewAttachment creates a valid Attachment
func NewAttachment(location *ArtifactLocation) *Attachment {
return &Attachment{ArtifactLocation: location}
}
// NewCodeFlow creates a valid CodeFlow
func NewCodeFlow(threadFlows ...*ThreadFlow) *CodeFlow {
return &CodeFlow{ThreadFlows: threadFlows}
}
// NewConfigurationOverride creates a valid ConfigurationOverride
func NewConfigurationOverride(configuration *ReportingConfiguration, descriptor *ReportingDescriptorReference) *ConfigurationOverride {
return &ConfigurationOverride{
Configuration: configuration,
Descriptor: descriptor,
}
}
// NewConversion creates a valid Conversion
func NewConversion(tool *Tool) *Conversion {
return &Conversion{Tool: tool}
}
// NewEdge creates a valid Edge
func NewEdge(id, sourceNodeId, targetNodeId string) *Edge {
return &Edge{
Id: id,
SourceNodeId: sourceNodeId,
TargetNodeId: targetNodeId,
}
}
// NewEdgeTraversal creates a valid EdgeTraversal
func NewEdgeTraversal(edgeId string) *EdgeTraversal {
return &EdgeTraversal{
EdgeId: edgeId,
}
}
// NewException creates a valid Exception
func NewException() *Exception {
return &Exception{}
}
// NewExternalProperties creates a valid ExternalProperties
func NewExternalProperties() *ExternalProperties {
return &ExternalProperties{}
}
// NewExternalPropertyFileReference creates a valid ExternalPropertyFileReference
func NewExternalPropertyFileReference() *ExternalPropertyFileReference {
return &ExternalPropertyFileReference{}
}
// NewExternalPropertyFileReferences creates a valid ExternalPropertyFileReferences
func NewExternalPropertyFileReferences() *ExternalPropertyFileReferences {
return &ExternalPropertyFileReferences{}
}
// NewFix creates a valid Fix
func NewFix(artifactChanges ...*ArtifactChange) *Fix {
return &Fix{
ArtifactChanges: artifactChanges,
}
}
// NewGraph creates a valid Graph
func NewGraph() *Graph {
return &Graph{}
}
// NewGraphTraversal creates a valid GraphTraversal
func NewGraphTraversal() *GraphTraversal {
return &GraphTraversal{}
}
// NewInvocation creates a valid Invocation
func NewInvocation(executionSuccessful bool) *Invocation {
return &Invocation{
ExecutionSuccessful: executionSuccessful,
}
}
// NewLocation creates a valid Location
func NewLocation() *Location {
return &Location{}
}
// NewLocationRelationship creates a valid LocationRelationship
func NewLocationRelationship(target int) *LocationRelationship {
return &LocationRelationship{
Target: target,
}
}
type LogFileVersion string
const Version210 LogFileVersion = "2.1.0"
// NewLogFile creates a valid LogFile
func NewLogFile(runs []*Run, version LogFileVersion) *LogFile {
return &LogFile{
Runs: runs,
Version: version,
}
}
// NewLogicalLocation creates a valid LogicalLocation
func NewLogicalLocation() *LogicalLocation {
return &LogicalLocation{}
}
// NewMessage creates a valid Message
func NewMessage() *Message {
return &Message{}
}
// NewMessageFromText creates a valid Message with the given text
func NewMessageFromText(text string) *Message {
return &Message{
Text: text,
}
}
// NewMultiformatMessageString creates a valid MultiformatMessageString
func NewMultiformatMessageString(text string) *MultiformatMessageString {
return &MultiformatMessageString{
Text: text,
}
}
// NewNode creates a valid Node
func NewNode(id string) *Node {
return &Node{
Id: id,
}
}
// NewNotification creates a valid Notification
func NewNotification(message *Message) *Notification {
return &Notification{
Message: message,
}
}
// NewPhysicalLocation creates a valid PhysicalLocation
func NewPhysicalLocation() *PhysicalLocation {
return &PhysicalLocation{}
}
// NewPropertyBag creates a valid PropertyBag
func NewPropertyBag() *PropertyBag {
return &PropertyBag{}
}
// NewRectangle creates a valid Rectangle
func NewRectangle() *Rectangle {
return &Rectangle{}
}
// NewRegion creates a valid Region
func NewRegion() *Region {
return &Region{}
}
// NewReplacement creates a valid Replacement
func NewReplacement(deletedRegion *Region) *Replacement {
return &Replacement{
DeletedRegion: deletedRegion,
}
}
// NewReportingConfiguration creates a valid ReportingConfiguration
func NewReportingConfiguration() *ReportingConfiguration {
return &ReportingConfiguration{}
}
// NewReportingDescriptor creates a valid ReportingDescriptor
func NewReportingDescriptor(id string) *ReportingDescriptor {
return &ReportingDescriptor{
Id: id,
}
}
// NewRule is an alias for NewReportingDescriptor
func NewRule(id string) *ReportingDescriptor {
return NewReportingDescriptor(id)
}
// NewReportingDescriptorReference creates a valid ReportingDescriptorReference
func NewReportingDescriptorReference() *ReportingDescriptorReference {
return &ReportingDescriptorReference{}
}
// NewReportingDescriptorRelationship creates a valid ReportingDescriptorRelationship
func NewReportingDescriptorRelationship(target *ReportingDescriptorReference) *ReportingDescriptorRelationship {
return &ReportingDescriptorRelationship{
Target: target,
}
}
// NewResult creates a valid Result
func NewResult(message *Message) *Result {
return &Result{
Message: message,
}
}
// NewResultProvenance creates a valid ResultProvenance
func NewResultProvenance() *ResultProvenance {
return &ResultProvenance{}
}
// NewRun creates a valid Run
func NewRun(tool *Tool) *Run {
return &Run{
Tool: tool,
}
}
// NewRunAutomationDetails creates a valid RunAutomationDetails
func NewRunAutomationDetails() *RunAutomationDetails {
return &RunAutomationDetails{}
}
// New creates a valid
func NewSpecialLocations() *SpecialLocations {
return &SpecialLocations{}
}
// NewStack creates a valid Stack
func NewStack(frames ...*StackFrame) *Stack {
return &Stack{
Frames: frames,
}
}
// NewStackFrame creates a valid StackFrame
func NewStackFrame() *StackFrame {
return &StackFrame{}
}
// NewSuppression creates a valid Suppression
func NewSuppression(kind string) *Suppression {
return &Suppression{
Kind: kind,
}
}
// NewThreadFlow creates a valid ThreadFlow
func NewThreadFlow(locations []*ThreadFlowLocation) *ThreadFlow {
return &ThreadFlow{
Locations: locations,
}
}
// NewThreadFlowLocation creates a valid ThreadFlowLocation
func NewThreadFlowLocation() *ThreadFlowLocation {
return &ThreadFlowLocation{}
}
// NewTool creates a valid Tool
func NewTool(driver *ToolComponent) *Tool {
return &Tool{
Driver: driver,
}
}
// NewToolComponent creates a valid ToolComponent
func NewToolComponent(name string) *ToolComponent {
return &ToolComponent{
Name: name,
}
}
// NewDriver is an alias for NewToolComponent
func NewDriver(name string) *ToolComponent {
return NewToolComponent(name)
}
// NewToolComponentReference creates a valid ToolComponentReference
func NewToolComponentReference() *ToolComponentReference {
return &ToolComponentReference{}
}
// NewTranslationMetadata creates a valid TranslationMetadata
func NewTranslationMetadata(name string) *TranslationMetadata {
return &TranslationMetadata{
Name: name,
}
}
// NewVersionControlDetails creates a valid VersionControlDetails
func NewVersionControlDetails(repositoryUri string) *VersionControlDetails {
return &VersionControlDetails{
RepositoryUri: repositoryUri,
}
}
// NewWebRequest creates a valid WebRequest
func NewWebRequest() *WebRequest {
return &WebRequest{}
}
// NewWebResponse creates a valid WebResponse
func NewWebResponse() *WebResponse {
return &WebResponse{}
}

@ -1,94 +0,0 @@
package garif
// WithLineColumn sets a physical location with the given line and column
func (l *Location) WithLineColumn(line, column int) *Location {
if l.PhysicalLocation == nil {
l.PhysicalLocation = NewPhysicalLocation()
}
l.PhysicalLocation.Region = NewRegion()
l.PhysicalLocation.Region.StartLine = line
l.PhysicalLocation.Region.StartColumn = column
return l
}
// WithURI sets a physical location with the given URI
func (l *Location) WithURI(uri string) *Location {
if l.PhysicalLocation == nil {
l.PhysicalLocation = NewPhysicalLocation()
}
l.PhysicalLocation.ArtifactLocation = NewArtifactLocation()
l.PhysicalLocation.ArtifactLocation.Uri = uri
return l
}
// WithKeyValue sets (overwrites) the value of the given key
func (b PropertyBag) WithKeyValue(key string, value interface{}) PropertyBag {
b[key] = value
return b
}
// WithHelpUri sets the help URI for this ReportingDescriptor
func (r *ReportingDescriptor) WithHelpUri(uri string) *ReportingDescriptor {
r.HelpUri = uri
return r
}
// WithProperties adds the key & value to the properties of this ReportingDescriptor
func (r *ReportingDescriptor) WithProperties(key string, value interface{}) *ReportingDescriptor {
if r.Properties == nil {
r.Properties = NewPropertyBag()
}
r.Properties.WithKeyValue(key, value)
return r
}
// WithArtifactsURIs adds the given URI as artifacts of this Run
func (r *Run) WithArtifactsURIs(uris ...string) *Run {
if r.Artifacts == nil {
r.Artifacts = []*Artifact{}
}
for _, uri := range uris {
a := NewArtifact()
a.Location = NewArtifactLocation()
a.Location.Uri = uri
r.Artifacts = append(r.Artifacts, a)
}
return r
}
// WithResult adds a result to this Run
func (r *Run) WithResult(ruleId string, message string, uri string, line int, column int) *Run {
if r.Results == nil {
r.Results = []*Result{}
}
msg := NewMessage()
msg.Text = message
result := NewResult(msg)
location := NewLocation().WithURI(uri).WithLineColumn(line, column)
result.Locations = append(result.Locations, location)
result.RuleId = ruleId
r.Results = append(r.Results, result)
return r
}
// WithInformationUri sets the information URI
func (t *ToolComponent) WithInformationUri(uri string) *ToolComponent {
t.InformationUri = uri
return t
}
// WithRules sets (overwrites) the rules
func (t *ToolComponent) WithRules(rules ...*ReportingDescriptor) *ToolComponent {
t.Rules = rules
return t
}

@ -1,11 +0,0 @@
// Package garif defines all the GO structures required to model a SARIF log file.
// These structures were created using the JSON-schema sarif-schema-2.1.0.json of SARIF logfiles
// available at https://github.com/oasis-tcs/sarif-spec/tree/master/Schemata.
//
// The package provides constructors for all structures (see constructors.go) These constructors
// ensure that the returned structure instantiation is valid with respect to the JSON schema and
// should be used in place of plain structure instantiation.
// The root structure is LogFile.
//
// The package provides utility decorators for the most commonly used structures (see decorators.go)
package garif

@ -1,5 +0,0 @@
module github.com/chavacava/garif
go 1.16
require github.com/stretchr/testify v1.7.0

@ -1,11 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -1,26 +0,0 @@
package garif
import (
"encoding/json"
"io"
)
// Write writes the JSON
func (l *LogFile) Write(w io.Writer) error {
marshal, err := json.Marshal(l)
if err != nil {
return err
}
_, err = w.Write(marshal)
return err
}
// PrettyWrite writes indented JSON
func (l *LogFile) PrettyWrite(w io.Writer) error {
marshal, err := json.MarshalIndent(l, "", " ")
if err != nil {
return err
}
_, err = w.Write(marshal)
return err
}

File diff suppressed because it is too large Load Diff

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Fatih Arslan
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.

@ -1,173 +0,0 @@
# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color)
Color lets you use colorized outputs in terms of [ANSI Escape
Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
has support for Windows too! The API can be used in several ways, pick one that
suits you.
![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg)
## Install
```bash
go get github.com/fatih/color
```
## Examples
### Standard colors
```go
// Print with default helper functions
color.Cyan("Prints text in cyan.")
// A newline will be appended automatically
color.Blue("Prints %s in blue.", "text")
// These are using the default foreground colors
color.Red("We have red")
color.Magenta("And many others ..")
```
### Mix and reuse colors
```go
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")
// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")
// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)
boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with white background.")
```
### Use your own output (io.Writer)
```go
// Use your own io.Writer output
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
blue := color.New(color.FgBlue)
blue.Fprint(writer, "This will print text in blue.")
```
### Custom print functions (PrintFunc)
```go
// Create a custom print function for convenience
red := color.New(color.FgRed).PrintfFunc()
red("Warning")
red("Error: %s", err)
// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("Don't forget this...")
```
### Custom fprint functions (FprintFunc)
```go
blue := color.New(FgBlue).FprintfFunc()
blue(myWriter, "important notice: %s", stars)
// Mix up with multiple attributes
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
success(myWriter, "Don't forget this...")
```
### Insert into noncolor strings (SprintFunc)
```go
// Create SprintXxx functions to mix strings with other non-colorized strings:
yellow := color.New(color.FgYellow).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
fmt.Printf("This %s rocks!\n", info("package"))
// Use helper functions
fmt.Println("This", color.RedString("warning"), "should be not neglected.")
fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.")
// Windows supported too! Just don't forget to change the output to color.Output
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
```
### Plug into existing code
```go
// Use handy standard colors
color.Set(color.FgYellow)
fmt.Println("Existing text will now be in yellow")
fmt.Printf("This one %s\n", "too")
color.Unset() // Don't forget to unset
// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // Use it in your function
fmt.Println("All text will now be bold magenta.")
```
### Disable/Enable color
There might be a case where you want to explicitly disable/enable color output. the
`go-isatty` package will automatically disable color output for non-tty output streams
(for example if the output were piped directly to `less`)
`Color` has support to disable/enable colors both globally and for single color
definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You
can easily disable the color output with:
```go
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
color.NoColor = true // disables colorized output
}
```
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
```go
c := color.New(color.FgCyan)
c.Println("Prints cyan text")
c.DisableColor()
c.Println("This is printed without any color")
c.EnableColor()
c.Println("This prints again cyan...")
```
## Todo
* Save/Return previous values
* Evaluate fmt.Formatter interface
## Credits
* [Fatih Arslan](https://github.com/fatih)
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)
## License
The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details

@ -1,603 +0,0 @@
package color
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
var (
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
NoColor = os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
// Output defines the standard output of the print functions. By default
// os.Stdout is used.
Output = colorable.NewColorableStdout()
// Error defines a color supporting writer for os.Stderr.
Error = colorable.NewColorableStderr()
// colorsCache is used to reduce the count of created Color objects and
// allows to reuse already created objects with required Attribute.
colorsCache = make(map[Attribute]*Color)
colorsCacheMu sync.Mutex // protects colorsCache
)
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attribute
noColor *bool
}
// Attribute defines a single SGR Code
type Attribute int
const escape = "\x1b"
// Base attributes
const (
Reset Attribute = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground text colors
const (
FgBlack Attribute = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground Hi-Intensity text colors
const (
FgHiBlack Attribute = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background text colors
const (
BgBlack Attribute = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background Hi-Intensity text colors
const (
BgHiBlack Attribute = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
// New returns a newly created color object.
func New(value ...Attribute) *Color {
c := &Color{params: make([]Attribute, 0)}
c.Add(value...)
return c
}
// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
c := New(p...)
c.Set()
return c
}
// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
if NoColor {
return
}
fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}
// Set sets the SGR sequence.
func (c *Color) Set() *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprintf(Output, c.format())
return c
}
func (c *Color) unset() {
if c.isNoColorSet() {
return
}
Unset()
}
func (c *Color) setWriter(w io.Writer) *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprintf(w, c.format())
return c
}
func (c *Color) unsetWriter(w io.Writer) {
if c.isNoColorSet() {
return
}
if NoColor {
return
}
fmt.Fprintf(w, "%s[%dm", escape, Reset)
}
// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
c.params = append(c.params, value...)
return c
}
func (c *Color) prepend(value Attribute) {
c.params = append(c.params, 0)
copy(c.params[1:], c.params[0:])
c.params[0] = value
}
// Fprint formats using the default formats for its operands and writes to w.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprint(w, a...)
}
// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprint(Output, a...)
}
// Fprintf formats according to a format specifier and writes to w.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprintf(w, format, a...)
}
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintf(Output, format, a...)
}
// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprintln(w, a...)
}
// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintln(Output, a...)
}
// Sprint is just like Print, but returns a string instead of printing it.
func (c *Color) Sprint(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
// Sprintln is just like Println, but returns a string instead of printing it.
func (c *Color) Sprintln(a ...interface{}) string {
return c.wrap(fmt.Sprintln(a...))
}
// Sprintf is just like Printf, but returns a string instead of printing it.
func (c *Color) Sprintf(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
// FprintFunc returns a new function that prints the passed arguments as
// colorized with color.Fprint().
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprint(w, a...)
}
}
// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
return func(a ...interface{}) {
c.Print(a...)
}
}
// FprintfFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintf().
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
return func(w io.Writer, format string, a ...interface{}) {
c.Fprintf(w, format, a...)
}
}
// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
return func(format string, a ...interface{}) {
c.Printf(format, a...)
}
}
// FprintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintln().
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprintln(w, a...)