github.com/nishanths/exhaustive (go): Package exhaustive defines an analyzer that checks exhaustiveness of switch statements of enum-like constants in Go source code. The analyzer can also optionally check exhaustiveness of keys in map literals whose key type is enum-like.  The Go language spec does not have an explicit definition for enums. For the purpose of this analyzer, and by convention, an enum type is any named type that:  In the example below, Biome is an enum type. The three constants are its enum members.  Enum member constants for an enum type must be declared in the same block as the type. The constant values may be specified using iota, literal values, or any valid means for declaring a Go constant. It is allowed for multiple enum member constants for an enum type to have the same constant value.  A switch statement that switches on a value of an enum type is exhaustive if all enum members are listed in the switch statement's cases. If multiple enum members have the same constant value, it is sufficient for any one of these same-valued members to be listed.  For an enum type defined in the same package as the switch statement, both exported and unexported enum members must be listed to satisfy exhaustiveness. For an enum type defined in an external package, it is sufficient that only exported enum members are listed. Only constant identifiers (e.g. Tundra, eco.Desert) listed in a switch statement's case clause can contribute towards satisfying exhaustiveness; other expressions, such as literal values and function calls, listed in case clauses do not contribute towards satisfying exhaustiveness.  By default, the existence of a default case in a switch statement does not unconditionally make a switch statement exhaustive. Use the -default-signifies-exhaustive flag to adjust this behavior.  For a map literal whose key type is an enum type, a similar definition of exhaustiveness applies. The map literal is considered exhaustive if all enum members are be listed in its keys. Empty map literals are never checked for exhaustiveness.  A switch statement that switches on a value whose type is a type parameter is checked for exhaustiveness if and only if each type element in the type constraint is an enum type and the type elements share the same underlying BasicKind.  For example, the switch statement below will be checked because each type element (i.e. M and N) in the type constraint is an enum type and the type elements share the same underlying BasicKind, namely int8. To satisfy exhaustiveness, the enum members collectively belonging to the enum types M and N (i.e. A, B, and C) must be listed in the switch statement's cases.  The analyzer handles type aliases as shown in the example below. newpkg.M is an enum type. oldpkg.M is an alias for newpkg.M. Note that oldpkg.M isn't itself an enum type; oldpkg.M is simply an alias for the actual enum type newpkg.M.  A switch statement that switches either on a value of type newpkg.M or of type oldpkg.M (which, being an alias, is just an alternative spelling for newpkg.M) is exhaustive if all of newpkg.M's enum members are listed in the switch statement's cases. The following switch statement is exhaustive.  The analyzer guarantees that introducing a type alias (such as type M = newpkg.M) will not result in new diagnostics if the set of enum member constant values of the RHS type is a subset of the set of enum member constant values of the LHS type.  Summary:  Descriptions:  To skip analysis of a switch statement or a map literal, associate it with a comment that begins with "//exhaustive:ignore". For example:  To ignore specific constants in exhaustiveness checks, specify the -ignore-enum-members flag:  To ignore specific types, specify the -ignore-enum-types flag:
Keywords: analysis|go|types