1
2
3
4
5 package specgen
6
7 import (
8 "fmt"
9 "strings"
10 )
11
12
13 type ParagraphKind int
14
15 const (
16
17 SpecOwned ParagraphKind = iota
18
19
20
21
22
23
24
25 ImplementationNote
26
27
28
29 DirectiveComment
30 )
31
32 func (k ParagraphKind) String() string {
33 switch k {
34 case SpecOwned:
35 return "spec-owned paragraph"
36 case ImplementationNote:
37 return "implementation note"
38 case DirectiveComment:
39 return "directive comment"
40 default:
41 return fmt.Sprintf("ParagraphKind(%d)", k)
42 }
43 }
44
45
46 type Paragraph struct {
47 Kind ParagraphKind
48 Text string
49 }
50
51
52
53 func HasNotePrefix(text string) bool {
54 if strings.HasPrefix(text, "Asm:") ||
55 strings.HasPrefix(text, "CPU Feature:") ||
56 strings.HasPrefix(text, "Deprecated:") ||
57 strings.HasPrefix(text, "Performance:") ||
58 strings.HasPrefix(text, "Note:") {
59 return true
60 }
61
62
63 if strings.HasPrefix(text, "Emulated,") || text == "Emulated" || strings.HasPrefix(text, "Emulated\n") || strings.HasPrefix(text, "Emulated:") {
64 return true
65 }
66 return false
67 }
68
69
70
71
72
73
74
75
76
77 func parseSpecDoc(ctx context, text string) []Paragraph {
78 text = strings.Trim(text, "\n")
79
80 var out []Paragraph
81 for para := range strings.SplitSeq(text, "\n\n") {
82
83 if HasNotePrefix(para) {
84 ctx.errorf("spec doc contains implementation note: %s", strings.TrimSpace(para))
85 } else {
86 out = append(out, Paragraph{SpecOwned, para})
87 }
88 }
89
90 return out
91 }
92
93
94
95
96
97
98
99
100 func FormatComment(paras []Paragraph) (string, error) {
101 if len(paras) == 0 {
102 return "", nil
103 }
104
105 lastKind := SpecOwned
106 for _, p := range paras {
107 if p.Kind < lastKind {
108 return "", fmt.Errorf("doc comment ordering violation: %s appeared after %s", p.Kind, lastKind)
109 }
110 lastKind = p.Kind
111 }
112
113 var buf strings.Builder
114 inDirectives := false
115 for i, p := range paras {
116 if i > 0 && !inDirectives {
117 buf.WriteString("//\n")
118 }
119 if p.Kind == DirectiveComment {
120 buf.WriteString("//")
121 buf.WriteString(p.Text)
122 buf.WriteByte('\n')
123
124 inDirectives = true
125 } else {
126 for line := range strings.SplitSeq(p.Text, "\n") {
127 if strings.HasPrefix(line, "\t") {
128 buf.WriteString("//")
129 } else {
130 buf.WriteString("// ")
131 }
132 buf.WriteString(line)
133 buf.WriteByte('\n')
134 }
135 }
136 }
137
138 return buf.String(), nil
139 }
140
View as plain text