func (b BlockedModules) Get() []string {
	modules := make([]string, len(b))
	for n := range b {
		for module := range b[n] {
			modules[n] = module
			break
		}
	}
	return modules
}
Get returns the module names that are blocked.
package gomodguard
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"github.com/Masterminds/semver"
	"golang.org/x/mod/modfile"
)
const (
	goModFilename       = "go.mod"
	errReadingGoModFile = "unable to read module file %s: %w"
	errParsingGoModFile = "unable to parse module file %s: %w"
)
var (
	blockReasonNotInAllowedList = "import of package `%s` is blocked because the module is not in the " +
		"allowed modules list."
	blockReasonInBlockedList = "import of package `%s` is blocked because the module is in the " +
		"blocked modules list."
	blockReasonHasLocalReplaceDirective = "import of package `%s` is blocked because the module has a " +
		"local replace directive."
)
type BlockedVersion struct {
	Version string `yaml:"version"`
	Reason  string `yaml:"reason"`
}
func (r *BlockedVersion) IsLintedModuleVersionBlocked(lintedModuleVersion string) bool {
	if r.Version == "" {
		return false
	}
	constraint, err := semver.NewConstraint(r.Version)
	if err != nil {
		return false
	}
	version, err := semver.NewVersion(lintedModuleVersion)
	if err != nil {
		return false
	}
	meet := constraint.Check(version)
	return meet
}
func (r *BlockedVersion) Message(lintedModuleVersion string) string {
	var sb strings.Builder
	_, _ = fmt.Fprintf(&sb, "version `%s` is blocked because it does not meet the version constraint `%s`.",
		lintedModuleVersion, r.Version)
	if r.Reason == "" {
		return sb.String()
	}
	_, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
	return sb.String()
}
type BlockedModule struct {
	Recommendations []string `yaml:"recommendations"`
	Reason          string   `yaml:"reason"`
}
func (r *BlockedModule) IsCurrentModuleARecommendation(currentModuleName string) bool {
	if r == nil {
		return false
	}
	for n := range r.Recommendations {
		if strings.TrimSpace(currentModuleName) == strings.TrimSpace(r.Recommendations[n]) {
			return true
		}
	}
	return false
}
func (r *BlockedModule) Message() string {
	var sb strings.Builder
	for i := range r.Recommendations {
		switch {
		case len(r.Recommendations) == 1:
			_, _ = fmt.Fprintf(&sb, "`%s` is a recommended module.", r.Recommendations[i])
		case (i+1) != len(r.Recommendations) && (i+1) == (len(r.Recommendations)-1):
			_, _ = fmt.Fprintf(&sb, "`%s` ", r.Recommendations[i])
		case (i + 1) != len(r.Recommendations):
			_, _ = fmt.Fprintf(&sb, "`%s`, ", r.Recommendations[i])
		default:
			_, _ = fmt.Fprintf(&sb, "and `%s` are recommended modules.", r.Recommendations[i])
		}
	}
	if r.Reason == "" {
		return sb.String()
	}
	if sb.Len() == 0 {
		_, _ = fmt.Fprintf(&sb, "%s.", strings.TrimRight(r.Reason, "."))
	} else {
		_, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
	}
	return sb.String()
}
func (r *BlockedModule) HasRecommendations() bool {
	if r == nil {
		return false
	}
	return len(r.Recommendations) > 0
}
type BlockedVersions []map[string]BlockedVersion
func (b BlockedVersions) Get() []string {
	modules := make([]string, len(b))
	for n := range b {
		for module := range b[n] {
			modules[n] = module
			break
		}
	}
	return modules
}
func (b BlockedVersions) GetBlockReason(lintedModuleName string) *BlockedVersion {
	for _, blockedModule := range b {
		for blockedModuleName, blockedVersion := range blockedModule {
			if strings.TrimSpace(lintedModuleName) == strings.TrimSpace(blockedModuleName) {
				return &blockedVersion
			}
		}
	}
	return nil
}
type BlockedModules []map[string]BlockedModule