-
Notifications
You must be signed in to change notification settings - Fork 11
/
comment.go
79 lines (70 loc) · 2.27 KB
/
comment.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package exhaustive
import (
"fmt"
"go/ast"
"go/token"
"strings"
)
const (
exhaustiveComment = "//exhaustive:"
ignoreComment = "ignore"
enforceComment = "enforce"
ignoreDefaultCaseRequiredComment = "ignore-default-case-required"
enforceDefaultCaseRequiredComment = "enforce-default-case-required"
)
type directive int64
const (
ignoreDirective = 1 << iota
enforceDirective
ignoreDefaultCaseRequiredDirective
enforceDefaultCaseRequiredDirective
)
type directiveSet int64
func parseDirectives(commentGroups []*ast.CommentGroup) (directiveSet, error) {
var out directiveSet
for _, commentGroup := range commentGroups {
if commentGroup == nil {
continue
}
for _, comment := range commentGroup.List {
commentLine := comment.Text
if !strings.HasPrefix(commentLine, exhaustiveComment) {
continue
}
directive := commentLine[len(exhaustiveComment):]
if whiteSpaceIndex := strings.IndexAny(directive, " \t"); whiteSpaceIndex != -1 {
directive = directive[:whiteSpaceIndex]
}
switch directive {
case ignoreComment:
out |= ignoreDirective
case enforceComment:
out |= enforceDirective
case ignoreDefaultCaseRequiredComment:
out |= ignoreDefaultCaseRequiredDirective
case enforceDefaultCaseRequiredComment:
out |= enforceDefaultCaseRequiredDirective
default:
return out, fmt.Errorf("invalid directive %q", directive)
}
}
}
return out, out.validate()
}
func (d directiveSet) has(directive directive) bool {
return int64(d)&int64(directive) != 0
}
func (d directiveSet) validate() error {
enforceConflict := ignoreDirective | enforceDirective
if d&(directiveSet(enforceConflict)) == directiveSet(enforceConflict) {
return fmt.Errorf("conflicting directives %q and %q", ignoreComment, enforceComment)
}
defaultCaseRequiredConflict := ignoreDefaultCaseRequiredDirective | enforceDefaultCaseRequiredDirective
if d&(directiveSet(defaultCaseRequiredConflict)) == directiveSet(defaultCaseRequiredConflict) {
return fmt.Errorf("conflicting directives %q and %q", ignoreDefaultCaseRequiredComment, enforceDefaultCaseRequiredComment)
}
return nil
}
func fileCommentMap(fset *token.FileSet, file *ast.File) ast.CommentMap {
return ast.NewCommentMap(fset, file, file.Comments)
}