pikeman 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|