aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/alecthomas
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/alecthomas')
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/.goreleaser.yml32
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/COPYING3
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/LICENSE-MIT21
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/README.md120
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/UNLICENSE24
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/check.go184
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/decl.go68
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/def.go157
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/doc.go53
-rw-r--r--vendor/github.com/alecthomas/go-check-sumtype/run.go26
10 files changed, 688 insertions, 0 deletions
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/.goreleaser.yml b/vendor/github.com/alecthomas/go-check-sumtype/.goreleaser.yml
new file mode 100644
index 000000000..33bd03d06
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/.goreleaser.yml
@@ -0,0 +1,32 @@
+project_name: go-check-sumtype
+release:
+ github:
+ owner: alecthomas
+ name: go-check-sumtype
+env:
+ - CGO_ENABLED=0
+builds:
+- goos:
+ - linux
+ - darwin
+ - windows
+ goarch:
+ - arm64
+ - amd64
+ - "386"
+ goarm:
+ - "6"
+ main: ./cmd/go-check-sumtype
+ binary: go-check-sumtype
+archives:
+ -
+ format: tar.gz
+ name_template: '{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{
+ .Arm }}{{ end }}'
+ files:
+ - COPYING
+ - README*
+snapshot:
+ name_template: SNAPSHOT-{{ .Commit }}
+checksum:
+ name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/COPYING b/vendor/github.com/alecthomas/go-check-sumtype/COPYING
new file mode 100644
index 000000000..bb9c20a09
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/COPYING
@@ -0,0 +1,3 @@
+This project is dual-licensed under the Unlicense and MIT licenses.
+
+You may use this code under the terms of either license.
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/LICENSE-MIT b/vendor/github.com/alecthomas/go-check-sumtype/LICENSE-MIT
new file mode 100644
index 000000000..3b0a5dc09
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Gallant
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/README.md b/vendor/github.com/alecthomas/go-check-sumtype/README.md
new file mode 100644
index 000000000..36614ef40
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/README.md
@@ -0,0 +1,120 @@
+**Note: This is a fork of the great project [go-sumtype](https://github.com/BurntSushi/go-sumtype) by BurntSushi.**
+**The original seems largely unmaintained, and the changes in this fork are backwards incompatible.**
+
+# go-check-sumtype [![CI](https://github.com/alecthomas/go-check-sumtype/actions/workflows/ci.yml/badge.svg)](https://github.com/alecthomas/go-check-sumtype/actions/workflows/ci.yml)
+A simple utility for running exhaustiveness checks on type switch statements.
+Exhaustiveness checks are only run on interfaces that are declared to be
+"sum types."
+
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+
+This work was inspired by our code at
+[Diffeo](https://diffeo.com).
+
+## Installation
+
+```go
+$ go get github.com/alecthomas/go-check-sumtype
+```
+
+For usage info, just run the command:
+
+```
+$ go-check-sumtype
+```
+
+Typical usage might look like this:
+
+```
+$ go-check-sumtype $(go list ./... | grep -v vendor)
+```
+
+## Usage
+
+`go-check-sumtype` takes a list of Go package paths or files and looks for sum type
+declarations in each package/file provided. Exhaustiveness checks are then
+performed for each use of a declared sum type in a type switch statement.
+Namely, `go-check-sumtype` will report an error for any type switch statement that
+either lacks a `default` clause or does not account for all possible variants.
+
+Declarations are provided in comments like so:
+
+```
+//sumtype:decl
+type MySumType interface { ... }
+```
+
+`MySumType` must be *sealed*. That is, part of its interface definition
+contains an unexported method.
+
+`go-check-sumtype` will produce an error if any of the above is not true.
+
+For valid declarations, `go-check-sumtype` will look for all occurrences in which a
+value of type `MySumType` participates in a type switch statement. In those
+occurrences, it will attempt to detect whether the type switch is exhaustive
+or not. If it's not, `go-check-sumtype` will report an error. For example, running
+`go-check-sumtype` on this source file:
+
+```go
+package main
+
+//sumtype:decl
+type MySumType interface {
+ sealed()
+}
+
+type VariantA struct{}
+
+func (*VariantA) sealed() {}
+
+type VariantB struct{}
+
+func (*VariantB) sealed() {}
+
+func main() {
+ switch MySumType(nil).(type) {
+ case *VariantA:
+ }
+}
+```
+
+produces the following:
+
+```
+$ sumtype mysumtype.go
+mysumtype.go:18:2: exhaustiveness check failed for sum type 'MySumType': missing cases for VariantB
+```
+
+Adding either a `default` clause or a clause to handle `*VariantB` will cause
+exhaustive checks to pass.
+
+As a special case, if the type switch statement contains a `default` clause
+that always panics, then exhaustiveness checks are still performed.
+
+## Details and motivation
+
+Sum types are otherwise known as discriminated unions. That is, a sum type is
+a finite set of disjoint values. In type systems that support sum types, the
+language will guarantee that if one has a sum type `T`, then its value must
+be one of its variants.
+
+Go's type system does not support sum types. A typical proxy for representing
+sum types in Go is to use an interface with an unexported method and define
+each variant of the sum type in the same package to satisfy said interface.
+This guarantees that the set of types that satisfy the interface is closed
+at compile time. Performing case analysis on these types is then done with
+a type switch statement, e.g., `switch x.(type) { ... }`. Each clause of the
+type switch corresponds to a *variant* of the sum type. The downside of this
+approach is that Go's type system is not aware of the set of variants, so it
+cannot tell you whether case analysis over a sum type is complete or not.
+
+The `go-check-sumtype` command recognizes this pattern, but it needs a small amount
+of help to recognize which interfaces should be treated as sum types, which
+is why the `//sumtype:decl` annotation is required. `go-check-sumtype` will
+figure out all of the variants of a sum type by finding the set of types
+defined in the same package that satisfy the interface specified by the
+declaration.
+
+The `go-check-sumtype` command will prove its worth when you need to add a variant
+to an existing sum type. Running `go-check-sumtype` will tell you immediately which
+case analyses need to be updated to account for the new variant.
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/UNLICENSE b/vendor/github.com/alecthomas/go-check-sumtype/UNLICENSE
new file mode 100644
index 000000000..68a49daad
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/check.go b/vendor/github.com/alecthomas/go-check-sumtype/check.go
new file mode 100644
index 000000000..21d751af4
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/check.go
@@ -0,0 +1,184 @@
+package gochecksumtype
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "sort"
+ "strings"
+
+ "golang.org/x/tools/go/packages"
+)
+
+// inexhaustiveError is returned from check for each occurrence of inexhaustive
+// case analysis in a Go type switch statement.
+type inexhaustiveError struct {
+ Position token.Position
+ Def sumTypeDef
+ Missing []types.Object
+}
+
+func (e inexhaustiveError) Pos() token.Position { return e.Position }
+func (e inexhaustiveError) Error() string {
+ return fmt.Sprintf(
+ "%s: exhaustiveness check failed for sum type %q (from %s): missing cases for %s",
+ e.Pos(), e.Def.Decl.TypeName, e.Def.Decl.Pos, strings.Join(e.Names(), ", "))
+}
+
+// Names returns a sorted list of names corresponding to the missing variant
+// cases.
+func (e inexhaustiveError) Names() []string {
+ var list []string
+ for _, o := range e.Missing {
+ list = append(list, o.Name())
+ }
+ sort.Strings(list)
+ return list
+}
+
+// check does exhaustiveness checking for the given sum type definitions in the
+// given package. Every instance of inexhaustive case analysis is returned.
+func check(pkg *packages.Package, defs []sumTypeDef) []error {
+ var errs []error
+ for _, astfile := range pkg.Syntax {
+ ast.Inspect(astfile, func(n ast.Node) bool {
+ swtch, ok := n.(*ast.TypeSwitchStmt)
+ if !ok {
+ return true
+ }
+ if err := checkSwitch(pkg, defs, swtch); err != nil {
+ errs = append(errs, err)
+ }
+ return true
+ })
+ }
+ return errs
+}
+
+// checkSwitch performs an exhaustiveness check on the given type switch
+// statement. If the type switch is used on a sum type and does not cover
+// all variants of that sum type, then an error is returned indicating which
+// variants were missed.
+//
+// Note that if the type switch contains a non-panicing default case, then
+// exhaustiveness checks are disabled.
+func checkSwitch(
+ pkg *packages.Package,
+ defs []sumTypeDef,
+ swtch *ast.TypeSwitchStmt,
+) error {
+ def, missing := missingVariantsInSwitch(pkg, defs, swtch)
+ if len(missing) > 0 {
+ return inexhaustiveError{
+ Position: pkg.Fset.Position(swtch.Pos()),
+ Def: *def,
+ Missing: missing,
+ }
+ }
+ return nil
+}
+
+// missingVariantsInSwitch returns a list of missing variants corresponding to
+// the given switch statement. The corresponding sum type definition is also
+// returned. (If no sum type definition could be found, then no exhaustiveness
+// checks are performed, and therefore, no missing variants are returned.)
+func missingVariantsInSwitch(
+ pkg *packages.Package,
+ defs []sumTypeDef,
+ swtch *ast.TypeSwitchStmt,
+) (*sumTypeDef, []types.Object) {
+ asserted := findTypeAssertExpr(swtch)
+ ty := pkg.TypesInfo.TypeOf(asserted)
+ def := findDef(defs, ty)
+ if def == nil {
+ // We couldn't find a corresponding sum type, so there's
+ // nothing we can do to check it.
+ return nil, nil
+ }
+ variantExprs, hasDefault := switchVariants(swtch)
+ if hasDefault && !defaultClauseAlwaysPanics(swtch) {
+ // A catch-all case defeats all exhaustiveness checks.
+ return def, nil
+ }
+ var variantTypes []types.Type
+ for _, expr := range variantExprs {
+ variantTypes = append(variantTypes, pkg.TypesInfo.TypeOf(expr))
+ }
+ return def, def.missing(variantTypes)
+}
+
+// switchVariants returns all case expressions found in a type switch. This
+// includes expressions from cases that have a list of expressions.
+func switchVariants(swtch *ast.TypeSwitchStmt) (exprs []ast.Expr, hasDefault bool) {
+ for _, stmt := range swtch.Body.List {
+ clause := stmt.(*ast.CaseClause)
+ if clause.List == nil {
+ hasDefault = true
+ } else {
+ exprs = append(exprs, clause.List...)
+ }
+ }
+ return
+}
+
+// defaultClauseAlwaysPanics returns true if the given switch statement has a
+// default clause that always panics. Note that this is done on a best-effort
+// basis. While there will never be any false positives, there may be false
+// negatives.
+//
+// If the given switch statement has no default clause, then this function
+// panics.
+func defaultClauseAlwaysPanics(swtch *ast.TypeSwitchStmt) bool {
+ var clause *ast.CaseClause
+ for _, stmt := range swtch.Body.List {
+ c := stmt.(*ast.CaseClause)
+ if c.List == nil {
+ clause = c
+ break
+ }
+ }
+ if clause == nil {
+ panic("switch statement has no default clause")
+ }
+ if len(clause.Body) != 1 {
+ return false
+ }
+ exprStmt, ok := clause.Body[0].(*ast.ExprStmt)
+ if !ok {
+ return false
+ }
+ callExpr, ok := exprStmt.X.(*ast.CallExpr)
+ if !ok {
+ return false
+ }
+ fun, ok := callExpr.Fun.(*ast.Ident)
+ if !ok {
+ return false
+ }
+ return fun.Name == "panic"
+}
+
+// findTypeAssertExpr extracts the expression that is being type asserted from a
+// type swtich statement.
+func findTypeAssertExpr(swtch *ast.TypeSwitchStmt) ast.Expr {
+ var expr ast.Expr
+ if assign, ok := swtch.Assign.(*ast.AssignStmt); ok {
+ expr = assign.Rhs[0]
+ } else {
+ expr = swtch.Assign.(*ast.ExprStmt).X
+ }
+ return expr.(*ast.TypeAssertExpr).X
+}
+
+// findDef returns the sum type definition corresponding to the given type. If
+// no such sum type definition exists, then nil is returned.
+func findDef(defs []sumTypeDef, needle types.Type) *sumTypeDef {
+ for i := range defs {
+ def := &defs[i]
+ if types.Identical(needle.Underlying(), def.Ty) {
+ return def
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/decl.go b/vendor/github.com/alecthomas/go-check-sumtype/decl.go
new file mode 100644
index 000000000..ea2cd06df
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/decl.go
@@ -0,0 +1,68 @@
+package gochecksumtype
+
+import (
+ "go/ast"
+ "go/token"
+ "strings"
+
+ "golang.org/x/tools/go/packages"
+)
+
+// sumTypeDecl is a declaration of a sum type in a Go source file.
+type sumTypeDecl struct {
+ // The package path that contains this decl.
+ Package *packages.Package
+ // The type named by this decl.
+ TypeName string
+ // Position where the declaration was found.
+ Pos token.Position
+}
+
+// Location returns a short string describing where this declaration was found.
+func (d sumTypeDecl) Location() string {
+ return d.Pos.String()
+}
+
+// findSumTypeDecls searches every package given for sum type declarations of
+// the form `sumtype:decl`.
+func findSumTypeDecls(pkgs []*packages.Package) ([]sumTypeDecl, error) {
+ var decls []sumTypeDecl
+ var retErr error
+ for _, pkg := range pkgs {
+ for _, file := range pkg.Syntax {
+ ast.Inspect(file, func(node ast.Node) bool {
+ if node == nil {
+ return true
+ }
+ decl, ok := node.(*ast.GenDecl)
+ if !ok || decl.Doc == nil {
+ return true
+ }
+ var tspec *ast.TypeSpec
+ for _, spec := range decl.Specs {
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+ tspec = ts
+ }
+ for _, line := range decl.Doc.List {
+ if !strings.HasPrefix(line.Text, "//sumtype:decl") {
+ continue
+ }
+ pos := pkg.Fset.Position(decl.Pos())
+ if tspec == nil {
+ retErr = notFoundError{Decl: sumTypeDecl{Package: pkg, Pos: pos}}
+ return false
+ }
+ pos = pkg.Fset.Position(tspec.Pos())
+ decl := sumTypeDecl{Package: pkg, TypeName: tspec.Name.Name, Pos: pos}
+ decls = append(decls, decl)
+ break
+ }
+ return true
+ })
+ }
+ }
+ return decls, retErr
+}
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/def.go b/vendor/github.com/alecthomas/go-check-sumtype/def.go
new file mode 100644
index 000000000..811b98f98
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/def.go
@@ -0,0 +1,157 @@
+package gochecksumtype
+
+import (
+ "fmt"
+ "go/token"
+ "go/types"
+)
+
+// Error as returned by Run()
+type Error interface {
+ error
+ Pos() token.Position
+}
+
+// unsealedError corresponds to a declared sum type whose interface is not
+// sealed. A sealed interface requires at least one unexported method.
+type unsealedError struct {
+ Decl sumTypeDecl
+}
+
+func (e unsealedError) Pos() token.Position { return e.Decl.Pos }
+func (e unsealedError) Error() string {
+ return fmt.Sprintf(
+ "%s: interface '%s' is not sealed "+
+ "(sealing requires at least one unexported method)",
+ e.Decl.Location(), e.Decl.TypeName)
+}
+
+// notFoundError corresponds to a declared sum type whose type definition
+// could not be found in the same Go package.
+type notFoundError struct {
+ Decl sumTypeDecl
+}
+
+func (e notFoundError) Pos() token.Position { return e.Decl.Pos }
+func (e notFoundError) Error() string {
+ return fmt.Sprintf("%s: type '%s' is not defined", e.Decl.Location(), e.Decl.TypeName)
+}
+
+// notInterfaceError corresponds to a declared sum type that does not
+// correspond to an interface.
+type notInterfaceError struct {
+ Decl sumTypeDecl
+}
+
+func (e notInterfaceError) Pos() token.Position { return e.Decl.Pos }
+func (e notInterfaceError) Error() string {
+ return fmt.Sprintf("%s: type '%s' is not an interface", e.Decl.Location(), e.Decl.TypeName)
+}
+
+// sumTypeDef corresponds to the definition of a Go interface that is
+// interpreted as a sum type. Its variants are determined by finding all types
+// that implement said interface in the same package.
+type sumTypeDef struct {
+ Decl sumTypeDecl
+ Ty *types.Interface
+ Variants []types.Object
+}
+
+// findSumTypeDefs attempts to find a Go type definition for each of the given
+// sum type declarations. If no such sum type definition could be found for
+// any of the given declarations, then an error is returned.
+func findSumTypeDefs(decls []sumTypeDecl) ([]sumTypeDef, []error) {
+ var defs []sumTypeDef
+ var errs []error
+ for _, decl := range decls {
+ def, err := newSumTypeDef(decl.Package.Types, decl)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ if def == nil {
+ errs = append(errs, notFoundError{decl})
+ continue
+ }
+ defs = append(defs, *def)
+ }
+ return defs, errs
+}
+
+// newSumTypeDef attempts to extract a sum type definition from a single
+// package. If no such type corresponds to the given decl, then this function
+// returns a nil def and a nil error.
+//
+// If the decl corresponds to a type that isn't an interface containing at
+// least one unexported method, then this returns an error.
+func newSumTypeDef(pkg *types.Package, decl sumTypeDecl) (*sumTypeDef, error) {
+ obj := pkg.Scope().Lookup(decl.TypeName)
+ if obj == nil {
+ return nil, nil
+ }
+ iface, ok := obj.Type().Underlying().(*types.Interface)
+ if !ok {
+ return nil, notInterfaceError{decl}
+ }
+ hasUnexported := false
+ for i := 0; i < iface.NumMethods(); i++ {
+ if !iface.Method(i).Exported() {
+ hasUnexported = true
+ break
+ }
+ }
+ if !hasUnexported {
+ return nil, unsealedError{decl}
+ }
+ def := &sumTypeDef{
+ Decl: decl,
+ Ty: iface,
+ }
+ for _, name := range pkg.Scope().Names() {
+ obj, ok := pkg.Scope().Lookup(name).(*types.TypeName)
+ if !ok {
+ continue
+ }
+ ty := obj.Type()
+ if types.Identical(ty.Underlying(), iface) {
+ continue
+ }
+ if types.Implements(ty, iface) || types.Implements(types.NewPointer(ty), iface) {
+ def.Variants = append(def.Variants, obj)
+ }
+ }
+ return def, nil
+}
+
+func (def *sumTypeDef) String() string {
+ return def.Decl.TypeName
+}
+
+// missing returns a list of variants in this sum type that are not in the
+// given list of types.
+func (def *sumTypeDef) missing(tys []types.Type) []types.Object {
+ // TODO(ag): This is O(n^2). Fix that. /shrug
+ var missing []types.Object
+ for _, v := range def.Variants {
+ found := false
+ varty := indirect(v.Type())
+ for _, ty := range tys {
+ ty = indirect(ty)
+ if types.Identical(varty, ty) {
+ found = true
+ }
+ }
+ if !found {
+ missing = append(missing, v)
+ }
+ }
+ return missing
+}
+
+// indirect dereferences through an arbitrary number of pointer types.
+func indirect(ty types.Type) types.Type {
+ if ty, ok := ty.(*types.Pointer); ok {
+ return indirect(ty.Elem())
+ }
+ return ty
+}
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/doc.go b/vendor/github.com/alecthomas/go-check-sumtype/doc.go
new file mode 100644
index 000000000..2b6e86764
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/doc.go
@@ -0,0 +1,53 @@
+/*
+sumtype takes a list of Go package paths or files and looks for sum type
+declarations in each package/file provided. Exhaustiveness checks are then
+performed for each use of a declared sum type in a type switch statement.
+Namely, sumtype will report an error for any type switch statement that
+either lacks a default clause or does not account for all possible variants.
+
+Declarations are provided in comments like so:
+
+ //sumtype:decl
+ type MySumType interface { ... }
+
+MySumType must be *sealed*. That is, part of its interface definition contains
+an unexported method.
+
+sumtype will produce an error if any of the above is not true.
+
+For valid declarations, sumtype will look for all occurrences in which a
+value of type MySumType participates in a type switch statement. In those
+occurrences, it will attempt to detect whether the type switch is exhaustive
+or not. If it's not, sumtype will report an error. For example:
+
+ $ cat mysumtype.go
+ package gochecksumtype
+
+ //sumtype:decl
+ type MySumType interface {
+ sealed()
+ }
+
+ type VariantA struct{}
+
+ func (a *VariantA) sealed() {}
+
+ type VariantB struct{}
+
+ func (b *VariantB) sealed() {}
+
+ func main() {
+ switch MySumType(nil).(type) {
+ case *VariantA:
+ }
+ }
+ $ sumtype mysumtype.go
+ mysumtype.go:18:2: exhaustiveness check failed for sum type 'MySumType': missing cases for VariantB
+
+Adding either a default clause or a clause to handle *VariantB will cause
+exhaustive checks to pass.
+
+As a special case, if the type switch statement contains a default clause
+that always panics, then exhaustiveness checks are still performed.
+*/
+package gochecksumtype
diff --git a/vendor/github.com/alecthomas/go-check-sumtype/run.go b/vendor/github.com/alecthomas/go-check-sumtype/run.go
new file mode 100644
index 000000000..fdcb643c5
--- /dev/null
+++ b/vendor/github.com/alecthomas/go-check-sumtype/run.go
@@ -0,0 +1,26 @@
+package gochecksumtype
+
+import "golang.org/x/tools/go/packages"
+
+// Run sumtype checking on the given packages.
+func Run(pkgs []*packages.Package) []error {
+ var errs []error
+
+ decls, err := findSumTypeDecls(pkgs)
+ if err != nil {
+ return []error{err}
+ }
+
+ defs, defErrs := findSumTypeDefs(decls)
+ errs = append(errs, defErrs...)
+ if len(defs) == 0 {
+ return errs
+ }
+
+ for _, pkg := range pkgs {
+ if pkgErrs := check(pkg, defs); pkgErrs != nil {
+ errs = append(errs, pkgErrs...)
+ }
+ }
+ return errs
+}