pikeman 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +21 -0
- data/CONTRIBUTING.md +15 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +27 -0
- data/LICENSE.txt +21 -0
- data/Makefile +39 -0
- data/README.md +85 -0
- data/Rakefile +10 -0
- data/VERSION +1 -0
- data/bin/console +14 -0
- data/bin/pikeman +15 -0
- data/bin/setup +8 -0
- data/golint/golint.go +213 -0
- data/golint/import.go +309 -0
- data/golint/version.go +3 -0
- data/lib/pikeman.rb +34 -0
- data/lib/pikeman/version.rb +3 -0
- data/lint.go +1708 -0
- data/lint_test.go +317 -0
- data/misc/emacs/golint.el +54 -0
- data/misc/vim/ftplugin/go/lint.vim +31 -0
- data/pikeman.gemspec +28 -0
- data/testdata/4.go +38 -0
- data/testdata/5_test.go +17 -0
- data/testdata/blank-import-lib.go +39 -0
- data/testdata/blank-import-lib_test.go +25 -0
- data/testdata/blank-import-main.go +14 -0
- data/testdata/broken.go +9 -0
- data/testdata/common-methods.go +16 -0
- data/testdata/const-block.go +36 -0
- data/testdata/context.go +24 -0
- data/testdata/contextkeytypes.go +38 -0
- data/testdata/else-multi.go +18 -0
- data/testdata/else.go +23 -0
- data/testdata/error-return.go +43 -0
- data/testdata/errorf.go +40 -0
- data/testdata/errors.go +38 -0
- data/testdata/iferr.go +101 -0
- data/testdata/import-dot.go +8 -0
- data/testdata/inc.go +14 -0
- data/testdata/names.go +116 -0
- data/testdata/pkg-caps.go +4 -0
- data/testdata/pkg-doc1.go +3 -0
- data/testdata/pkg-doc2.go +5 -0
- data/testdata/pkg-doc3.go +7 -0
- data/testdata/pkg-doc4.go +7 -0
- data/testdata/pkg-doc5.go +9 -0
- data/testdata/pkg-main.go +5 -0
- data/testdata/range.go +43 -0
- data/testdata/receiver-names.go +49 -0
- data/testdata/sort.go +20 -0
- data/testdata/stutter.go +25 -0
- data/testdata/time.go +13 -0
- data/testdata/unexp-return.go +46 -0
- data/testdata/var-decl.go +86 -0
- metadata +172 -0
data/lint_test.go
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
// Copyright (c) 2013 The Go Authors. All rights reserved.
|
2
|
+
//
|
3
|
+
// Use of this source code is governed by a BSD-style
|
4
|
+
// license that can be found in the LICENSE file or at
|
5
|
+
// https://developers.google.com/open-source/licenses/bsd.
|
6
|
+
|
7
|
+
package lint
|
8
|
+
|
9
|
+
import (
|
10
|
+
"bytes"
|
11
|
+
"flag"
|
12
|
+
"fmt"
|
13
|
+
"go/ast"
|
14
|
+
"go/parser"
|
15
|
+
"go/printer"
|
16
|
+
"go/token"
|
17
|
+
"go/types"
|
18
|
+
"io/ioutil"
|
19
|
+
"path"
|
20
|
+
"regexp"
|
21
|
+
"strconv"
|
22
|
+
"strings"
|
23
|
+
"testing"
|
24
|
+
)
|
25
|
+
|
26
|
+
var lintMatch = flag.String("lint.match", "", "restrict testdata matches to this pattern")
|
27
|
+
|
28
|
+
func TestAll(t *testing.T) {
|
29
|
+
l := new(Linter)
|
30
|
+
rx, err := regexp.Compile(*lintMatch)
|
31
|
+
if err != nil {
|
32
|
+
t.Fatalf("Bad -lint.match value %q: %v", *lintMatch, err)
|
33
|
+
}
|
34
|
+
|
35
|
+
baseDir := "testdata"
|
36
|
+
fis, err := ioutil.ReadDir(baseDir)
|
37
|
+
if err != nil {
|
38
|
+
t.Fatalf("ioutil.ReadDir: %v", err)
|
39
|
+
}
|
40
|
+
if len(fis) == 0 {
|
41
|
+
t.Fatalf("no files in %v", baseDir)
|
42
|
+
}
|
43
|
+
for _, fi := range fis {
|
44
|
+
if !rx.MatchString(fi.Name()) {
|
45
|
+
continue
|
46
|
+
}
|
47
|
+
//t.Logf("Testing %s", fi.Name())
|
48
|
+
src, err := ioutil.ReadFile(path.Join(baseDir, fi.Name()))
|
49
|
+
if err != nil {
|
50
|
+
t.Fatalf("Failed reading %s: %v", fi.Name(), err)
|
51
|
+
}
|
52
|
+
|
53
|
+
ins := parseInstructions(t, fi.Name(), src)
|
54
|
+
if ins == nil {
|
55
|
+
t.Errorf("Test file %v does not have instructions", fi.Name())
|
56
|
+
continue
|
57
|
+
}
|
58
|
+
|
59
|
+
ps, err := l.Lint(fi.Name(), src)
|
60
|
+
if err != nil {
|
61
|
+
t.Errorf("Linting %s: %v", fi.Name(), err)
|
62
|
+
continue
|
63
|
+
}
|
64
|
+
|
65
|
+
for _, in := range ins {
|
66
|
+
ok := false
|
67
|
+
for i, p := range ps {
|
68
|
+
if p.Position.Line != in.Line {
|
69
|
+
continue
|
70
|
+
}
|
71
|
+
if in.Match.MatchString(p.Text) {
|
72
|
+
// check replacement if we are expecting one
|
73
|
+
if in.Replacement != "" {
|
74
|
+
// ignore any inline comments, since that would be recursive
|
75
|
+
r := p.ReplacementLine
|
76
|
+
if i := strings.Index(r, " //"); i >= 0 {
|
77
|
+
r = r[:i]
|
78
|
+
}
|
79
|
+
if r != in.Replacement {
|
80
|
+
t.Errorf("Lint failed at %s:%d; got replacement %q, want %q", fi.Name(), in.Line, r, in.Replacement)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
// remove this problem from ps
|
85
|
+
copy(ps[i:], ps[i+1:])
|
86
|
+
ps = ps[:len(ps)-1]
|
87
|
+
|
88
|
+
//t.Logf("/%v/ matched at %s:%d", in.Match, fi.Name(), in.Line)
|
89
|
+
ok = true
|
90
|
+
break
|
91
|
+
}
|
92
|
+
}
|
93
|
+
if !ok {
|
94
|
+
t.Errorf("Lint failed at %s:%d; /%v/ did not match", fi.Name(), in.Line, in.Match)
|
95
|
+
}
|
96
|
+
}
|
97
|
+
for _, p := range ps {
|
98
|
+
t.Errorf("Unexpected problem at %s:%d: %v", fi.Name(), p.Position.Line, p.Text)
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
type instruction struct {
|
104
|
+
Line int // the line number this applies to
|
105
|
+
Match *regexp.Regexp // what pattern to match
|
106
|
+
Replacement string // what the suggested replacement line should be
|
107
|
+
}
|
108
|
+
|
109
|
+
// parseInstructions parses instructions from the comments in a Go source file.
|
110
|
+
// It returns nil if none were parsed.
|
111
|
+
func parseInstructions(t *testing.T, filename string, src []byte) []instruction {
|
112
|
+
fset := token.NewFileSet()
|
113
|
+
f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
|
114
|
+
if err != nil {
|
115
|
+
t.Fatalf("Test file %v does not parse: %v", filename, err)
|
116
|
+
}
|
117
|
+
var ins []instruction
|
118
|
+
for _, cg := range f.Comments {
|
119
|
+
ln := fset.Position(cg.Pos()).Line
|
120
|
+
raw := cg.Text()
|
121
|
+
for _, line := range strings.Split(raw, "\n") {
|
122
|
+
if line == "" || strings.HasPrefix(line, "#") {
|
123
|
+
continue
|
124
|
+
}
|
125
|
+
if line == "OK" && ins == nil {
|
126
|
+
// so our return value will be non-nil
|
127
|
+
ins = make([]instruction, 0)
|
128
|
+
continue
|
129
|
+
}
|
130
|
+
if strings.Contains(line, "MATCH") {
|
131
|
+
rx, err := extractPattern(line)
|
132
|
+
if err != nil {
|
133
|
+
t.Fatalf("At %v:%d: %v", filename, ln, err)
|
134
|
+
}
|
135
|
+
matchLine := ln
|
136
|
+
if i := strings.Index(line, "MATCH:"); i >= 0 {
|
137
|
+
// This is a match for a different line.
|
138
|
+
lns := strings.TrimPrefix(line[i:], "MATCH:")
|
139
|
+
lns = lns[:strings.Index(lns, " ")]
|
140
|
+
matchLine, err = strconv.Atoi(lns)
|
141
|
+
if err != nil {
|
142
|
+
t.Fatalf("Bad match line number %q at %v:%d: %v", lns, filename, ln, err)
|
143
|
+
}
|
144
|
+
}
|
145
|
+
var repl string
|
146
|
+
if r, ok := extractReplacement(line); ok {
|
147
|
+
repl = r
|
148
|
+
}
|
149
|
+
ins = append(ins, instruction{
|
150
|
+
Line: matchLine,
|
151
|
+
Match: rx,
|
152
|
+
Replacement: repl,
|
153
|
+
})
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
return ins
|
158
|
+
}
|
159
|
+
|
160
|
+
func extractPattern(line string) (*regexp.Regexp, error) {
|
161
|
+
a, b := strings.Index(line, "/"), strings.LastIndex(line, "/")
|
162
|
+
if a == -1 || a == b {
|
163
|
+
return nil, fmt.Errorf("malformed match instruction %q", line)
|
164
|
+
}
|
165
|
+
pat := line[a+1 : b]
|
166
|
+
rx, err := regexp.Compile(pat)
|
167
|
+
if err != nil {
|
168
|
+
return nil, fmt.Errorf("bad match pattern %q: %v", pat, err)
|
169
|
+
}
|
170
|
+
return rx, nil
|
171
|
+
}
|
172
|
+
|
173
|
+
func extractReplacement(line string) (string, bool) {
|
174
|
+
// Look for this: / -> `
|
175
|
+
// (the end of a match and start of a backtick string),
|
176
|
+
// and then the closing backtick.
|
177
|
+
const start = "/ -> `"
|
178
|
+
a, b := strings.Index(line, start), strings.LastIndex(line, "`")
|
179
|
+
if a < 0 || a > b {
|
180
|
+
return "", false
|
181
|
+
}
|
182
|
+
return line[a+len(start) : b], true
|
183
|
+
}
|
184
|
+
|
185
|
+
func render(fset *token.FileSet, x interface{}) string {
|
186
|
+
var buf bytes.Buffer
|
187
|
+
if err := printer.Fprint(&buf, fset, x); err != nil {
|
188
|
+
panic(err)
|
189
|
+
}
|
190
|
+
return buf.String()
|
191
|
+
}
|
192
|
+
|
193
|
+
func TestLine(t *testing.T) {
|
194
|
+
tests := []struct {
|
195
|
+
src string
|
196
|
+
offset int
|
197
|
+
want string
|
198
|
+
}{
|
199
|
+
{"single line file", 5, "single line file"},
|
200
|
+
{"single line file with newline\n", 5, "single line file with newline\n"},
|
201
|
+
{"first\nsecond\nthird\n", 2, "first\n"},
|
202
|
+
{"first\nsecond\nthird\n", 9, "second\n"},
|
203
|
+
{"first\nsecond\nthird\n", 14, "third\n"},
|
204
|
+
{"first\nsecond\nthird with no newline", 16, "third with no newline"},
|
205
|
+
{"first byte\n", 0, "first byte\n"},
|
206
|
+
}
|
207
|
+
for _, test := range tests {
|
208
|
+
got := srcLine([]byte(test.src), token.Position{Offset: test.offset})
|
209
|
+
if got != test.want {
|
210
|
+
t.Errorf("srcLine(%q, offset=%d) = %q, want %q", test.src, test.offset, got, test.want)
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
func TestLintName(t *testing.T) {
|
216
|
+
tests := []struct {
|
217
|
+
name, want string
|
218
|
+
}{
|
219
|
+
{"foo_bar", "fooBar"},
|
220
|
+
{"foo_bar_baz", "fooBarBaz"},
|
221
|
+
{"Foo_bar", "FooBar"},
|
222
|
+
{"foo_WiFi", "fooWiFi"},
|
223
|
+
{"id", "id"},
|
224
|
+
{"Id", "ID"},
|
225
|
+
{"foo_id", "fooID"},
|
226
|
+
{"fooId", "fooID"},
|
227
|
+
{"fooUid", "fooUID"},
|
228
|
+
{"idFoo", "idFoo"},
|
229
|
+
{"uidFoo", "uidFoo"},
|
230
|
+
{"midIdDle", "midIDDle"},
|
231
|
+
{"APIProxy", "APIProxy"},
|
232
|
+
{"ApiProxy", "APIProxy"},
|
233
|
+
{"apiProxy", "apiProxy"},
|
234
|
+
{"_Leading", "_Leading"},
|
235
|
+
{"___Leading", "_Leading"},
|
236
|
+
{"trailing_", "trailing"},
|
237
|
+
{"trailing___", "trailing"},
|
238
|
+
{"a_b", "aB"},
|
239
|
+
{"a__b", "aB"},
|
240
|
+
{"a___b", "aB"},
|
241
|
+
{"Rpc1150", "RPC1150"},
|
242
|
+
{"case3_1", "case3_1"},
|
243
|
+
{"case3__1", "case3_1"},
|
244
|
+
{"IEEE802_16bit", "IEEE802_16bit"},
|
245
|
+
{"IEEE802_16Bit", "IEEE802_16Bit"},
|
246
|
+
}
|
247
|
+
for _, test := range tests {
|
248
|
+
got := lintName(test.name)
|
249
|
+
if got != test.want {
|
250
|
+
t.Errorf("lintName(%q) = %q, want %q", test.name, got, test.want)
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
func TestExportedType(t *testing.T) {
|
256
|
+
tests := []struct {
|
257
|
+
typString string
|
258
|
+
exp bool
|
259
|
+
}{
|
260
|
+
{"int", true},
|
261
|
+
{"string", false}, // references the shadowed builtin "string"
|
262
|
+
{"T", true},
|
263
|
+
{"t", false},
|
264
|
+
{"*T", true},
|
265
|
+
{"*t", false},
|
266
|
+
{"map[int]complex128", true},
|
267
|
+
}
|
268
|
+
for _, test := range tests {
|
269
|
+
src := `package foo; type T int; type t int; type string struct{}`
|
270
|
+
fset := token.NewFileSet()
|
271
|
+
file, err := parser.ParseFile(fset, "foo.go", src, 0)
|
272
|
+
if err != nil {
|
273
|
+
t.Fatalf("Parsing %q: %v", src, err)
|
274
|
+
}
|
275
|
+
// use the package name as package path
|
276
|
+
config := &types.Config{}
|
277
|
+
pkg, err := config.Check(file.Name.Name, fset, []*ast.File{file}, nil)
|
278
|
+
if err != nil {
|
279
|
+
t.Fatalf("Type checking %q: %v", src, err)
|
280
|
+
}
|
281
|
+
tv, err := types.Eval(fset, pkg, token.NoPos, test.typString)
|
282
|
+
if err != nil {
|
283
|
+
t.Errorf("types.Eval(%q): %v", test.typString, err)
|
284
|
+
continue
|
285
|
+
}
|
286
|
+
if got := exportedType(tv.Type); got != test.exp {
|
287
|
+
t.Errorf("exportedType(%v) = %t, want %t", tv.Type, got, test.exp)
|
288
|
+
}
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
func TestIsGenerated(t *testing.T) {
|
293
|
+
tests := []struct {
|
294
|
+
source string
|
295
|
+
generated bool
|
296
|
+
}{
|
297
|
+
{"// Code Generated by some tool. DO NOT EDIT.", false},
|
298
|
+
{"// Code generated by some tool. DO NOT EDIT.", true},
|
299
|
+
{"// Code generated by some tool. DO NOT EDIT", false},
|
300
|
+
{"// Code generated DO NOT EDIT.", true},
|
301
|
+
{"// Code generated DO NOT EDIT.", false},
|
302
|
+
{"\t\t// Code generated by some tool. DO NOT EDIT.\npackage foo\n", false},
|
303
|
+
{"// Code generated by some tool. DO NOT EDIT.\npackage foo\n", true},
|
304
|
+
{"package foo\n// Code generated by some tool. DO NOT EDIT.\ntype foo int\n", true},
|
305
|
+
{"package foo\n // Code generated by some tool. DO NOT EDIT.\ntype foo int\n", false},
|
306
|
+
{"package foo\n// Code generated by some tool. DO NOT EDIT. \ntype foo int\n", false},
|
307
|
+
{"package foo\ntype foo int\n// Code generated by some tool. DO NOT EDIT.\n", true},
|
308
|
+
{"package foo\ntype foo int\n// Code generated by some tool. DO NOT EDIT.", true},
|
309
|
+
}
|
310
|
+
|
311
|
+
for i, test := range tests {
|
312
|
+
got := isGenerated([]byte(test.source))
|
313
|
+
if got != test.generated {
|
314
|
+
t.Errorf("test %d, isGenerated() = %v, want %v", i, got, test.generated)
|
315
|
+
}
|
316
|
+
}
|
317
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
;;; golint.el --- lint for the Go source code
|
2
|
+
|
3
|
+
;; Copyright 2013 The Go Authors. All rights reserved.
|
4
|
+
|
5
|
+
;; License: BSD-3-clause
|
6
|
+
;; URL: https://github.com/golang/lint
|
7
|
+
|
8
|
+
;;; Commentary:
|
9
|
+
|
10
|
+
;; To install golint, add the following lines to your .emacs file:
|
11
|
+
;; (add-to-list 'load-path "PATH CONTAINING golint.el" t)
|
12
|
+
;; (require 'golint)
|
13
|
+
;;
|
14
|
+
;; After this, type M-x golint on Go source code.
|
15
|
+
;;
|
16
|
+
;; Usage:
|
17
|
+
;; C-x `
|
18
|
+
;; Jump directly to the line in your code which caused the first message.
|
19
|
+
;;
|
20
|
+
;; For more usage, see Compilation-Mode:
|
21
|
+
;; http://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html
|
22
|
+
|
23
|
+
;;; Code:
|
24
|
+
|
25
|
+
(require 'compile)
|
26
|
+
|
27
|
+
(defun go-lint-buffer-name (mode)
|
28
|
+
"*Golint*")
|
29
|
+
|
30
|
+
(defun golint-process-setup ()
|
31
|
+
"Setup compilation variables and buffer for `golint'."
|
32
|
+
(run-hooks 'golint-setup-hook))
|
33
|
+
|
34
|
+
(define-compilation-mode golint-mode "golint"
|
35
|
+
"Golint is a linter for Go source code."
|
36
|
+
(set (make-local-variable 'compilation-scroll-output) nil)
|
37
|
+
(set (make-local-variable 'compilation-disable-input) t)
|
38
|
+
(set (make-local-variable 'compilation-process-setup-function)
|
39
|
+
'golint-process-setup))
|
40
|
+
|
41
|
+
;;;###autoload
|
42
|
+
(defun golint ()
|
43
|
+
"Run golint on the current file and populate the fix list.
|
44
|
+
Pressing \"C-x `\" jumps directly to the line in your code which
|
45
|
+
caused the first message."
|
46
|
+
(interactive)
|
47
|
+
(compilation-start
|
48
|
+
(mapconcat #'shell-quote-argument
|
49
|
+
(list "golint" (expand-file-name buffer-file-name)) " ")
|
50
|
+
'golint-mode))
|
51
|
+
|
52
|
+
(provide 'golint)
|
53
|
+
|
54
|
+
;;; golint.el ends here
|
@@ -0,0 +1,31 @@
|
|
1
|
+
" Copyright 2013 The Go Authors. All rights reserved.
|
2
|
+
" Use of this source code is governed by a BSD-style
|
3
|
+
" license that can be found in the LICENSE file.
|
4
|
+
"
|
5
|
+
" lint.vim: Vim command to lint Go files with golint.
|
6
|
+
"
|
7
|
+
" https://github.com/golang/lint
|
8
|
+
"
|
9
|
+
" This filetype plugin add a new commands for go buffers:
|
10
|
+
"
|
11
|
+
" :Lint
|
12
|
+
"
|
13
|
+
" Run golint for the current Go file.
|
14
|
+
"
|
15
|
+
if exists("b:did_ftplugin_go_lint")
|
16
|
+
finish
|
17
|
+
endif
|
18
|
+
|
19
|
+
if !executable("golint")
|
20
|
+
finish
|
21
|
+
endif
|
22
|
+
|
23
|
+
command! -buffer Lint call s:GoLint()
|
24
|
+
|
25
|
+
function! s:GoLint() abort
|
26
|
+
cexpr system('golint ' . shellescape(expand('%')))
|
27
|
+
endfunction
|
28
|
+
|
29
|
+
let b:did_ftplugin_go_lint = 1
|
30
|
+
|
31
|
+
" vim:ts=4:sw=4:et
|
data/pikeman.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "pikeman/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "pikeman"
|
7
|
+
spec.version = Pikeman::VERSION
|
8
|
+
spec.authors = ["Maxime Bedard"]
|
9
|
+
spec.email = ["maxime.bedard@shopify.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Very opinionated version of google/golint}
|
12
|
+
spec.description = %q{Very opinionated version of google/golint}
|
13
|
+
spec.homepage = "https://github.com/maximebedard/pikeman"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
|
20
|
+
spec.executables = ["pikeman"]
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "cli-kit"
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
27
|
+
spec.add_development_dependency "pry-byebug"
|
28
|
+
end
|
data/testdata/4.go
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
// Test that exported names have correct comments.
|
2
|
+
|
3
|
+
// Package pkg does something.
|
4
|
+
package pkg
|
5
|
+
|
6
|
+
import "time"
|
7
|
+
|
8
|
+
type T int // MATCH /exported type T.*should.*comment.*or.*unexport/
|
9
|
+
|
10
|
+
func (T) F() {} // MATCH /exported method T\.F.*should.*comment.*or.*unexport/
|
11
|
+
|
12
|
+
// this is a nice type.
|
13
|
+
// MATCH /comment.*exported type U.*should.*form.*"U ..."/
|
14
|
+
type U string
|
15
|
+
|
16
|
+
// this is a neat function.
|
17
|
+
// MATCH /comment.*exported method U\.G.*should.*form.*"G ..."/
|
18
|
+
func (U) G() {}
|
19
|
+
|
20
|
+
// A V is a string.
|
21
|
+
type V string
|
22
|
+
|
23
|
+
// V.H has a pointer receiver
|
24
|
+
|
25
|
+
func (*V) H() {} // MATCH /exported method V\.H.*should.*comment.*or.*unexport/
|
26
|
+
|
27
|
+
var W = "foo" // MATCH /exported var W.*should.*comment.*or.*unexport/
|
28
|
+
|
29
|
+
const X = "bar" // MATCH /exported const X.*should.*comment.*or.*unexport/
|
30
|
+
|
31
|
+
var Y, Z int // MATCH /exported var Z.*own declaration/
|
32
|
+
|
33
|
+
// Location should be okay, since the other var name is an underscore.
|
34
|
+
var Location, _ = time.LoadLocation("Europe/Istanbul") // not Constantinople
|
35
|
+
|
36
|
+
// this is improperly documented
|
37
|
+
// MATCH /comment.*const.*Thing.*form.*"Thing ..."/
|
38
|
+
const Thing = "wonderful"
|