|
|
Created:
13 years, 4 months ago by r Modified:
13 years, 4 months ago Reviewers:
CC:
rsc, gri, niemeyer, iant2, rog, lstoakes, jacek.masiulaniec_gmail.com, cw, golang-dev Visibility:
Public. |
Descriptiongovet: a new static checker for Go programs.
At the moment, and for the forseeable future, it only checks arguments to print calls.
Patch Set 1 #
Total comments: 33
Patch Set 2 : code review 3522041: gocheck: a new static checker for Go programs. #Patch Set 3 : code review 3522041: gocheck: a new static checker for Go programs. #Patch Set 4 : code review 3522041: gocheck: a new static checker for Go programs. #Patch Set 5 : code review 3522041: gocheck: a new static checker for Go programs. #
Total comments: 6
Patch Set 6 : code review 3522041: gocheck: a new static checker for Go programs. #Patch Set 7 : code review 3522041: gocheck: a new static checker for Go programs. #
Total comments: 1
Patch Set 8 : code review 3522041: govet: a new static checker for Go programs. #Patch Set 9 : code review 3522041: govet: a new static checker for Go programs. #
Total comments: 7
Patch Set 10 : code review 3522041: govet: a new static checker for Go programs. #Patch Set 11 : code review 3522041: govet: a new static checker for Go programs. #
Total comments: 1
Patch Set 12 : code review 3522041: govet: a new static checker for Go programs. #
Total comments: 1
Patch Set 13 : code review 3522041: govet: a new static checker for Go programs. #Patch Set 14 : code review 3522041: govet: a new static checker for Go programs. #
MessagesTotal messages: 35
Hello rsc, gri (cc: golang-dev@googlegroups.com), I'd like you to review this change.
Sign in to reply to this message.
Hello rsc, gri (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/doc.go File src/cmd/gocheck/doc.go (right): http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/doc.go#newcode16 src/cmd/gocheck/doc.go:16: a format descriptor string in the manner of fmt.Printf. a If not, gocheck warns about arguments that look like format descriptor strings. . http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:27: var helpString = `By default gocheck checks for functions from This is already out of date (-funcs below). Leave for [godoc gocheck] to print instead? http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:48: if *help { I'm uncomfortable with this precedent (see above). http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:78: die(`illegal format for "Func:N" argument "%s"; %s`, name, err) s/"%s"/%q/ http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:93: for i := 0; i < flag.NArg(); i++ { for _, arg := range flag.Args() { http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:116: fmt.Fprintf(os.Stderr, "gocheckprint: "+format+"\n", args...) s2/print// http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:120: // Println is fmt.Println guarded by --v. s/--/-/ (not incorrect but unnecessary) http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:128: // Printf is fmt.Printf guarded by --v. s/--/-/ http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:161: func (f *File) checkFile(name string, file *ast.File) { I think much of this can go away if you use ast.Walk. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:340: "Printf": 0, "Println": 0, s/f// .+1s/f// http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:361: arg := call.Args[skip] check len(call.Args) http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:373: f.Badf(call.Pos(), "no formatting directive in %s call", name) I don't think this is bad. Programs that, say, use Printf consistently seem fine. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:397: var percent = []byte{'%'} can use IndexByte below instead http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:405: args := call.Args check len(call.Args) http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:408: f.Badf(call.Pos(), "no args in %s call", name) I don't think this is worth complaining about until the code can distinction fmt.Print() from log.Print() http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:415: f.Badf(call.Pos(), "formatting directive in %s call", name) s/formatting/possible &
Sign in to reply to this message.
Hello rsc, gri (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:27: var helpString = `By default gocheck checks for functions from On 2010/12/08 21:33:28, rsc1 wrote: > This is already out of date (-funcs below). > Leave for [godoc gocheck] to print instead? i'm torn too. i like the command to give me information. plus people don't seem to know that godoc describes commands. but ok. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:78: die(`illegal format for "Func:N" argument "%s"; %s`, name, err) On 2010/12/08 21:33:28, rsc1 wrote: > s/"%s"/%q/ Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:93: for i := 0; i < flag.NArg(); i++ { On 2010/12/08 21:33:28, rsc1 wrote: > for _, arg := range flag.Args() { Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:116: fmt.Fprintf(os.Stderr, "gocheckprint: "+format+"\n", args...) On 2010/12/08 21:33:28, rsc1 wrote: > s2/print// Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:120: // Println is fmt.Println guarded by --v. On 2010/12/08 21:33:28, rsc1 wrote: > s/--/-/ > (not incorrect but unnecessary) Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:128: // Printf is fmt.Printf guarded by --v. On 2010/12/08 21:33:28, rsc1 wrote: > s/--/-/ Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:161: func (f *File) checkFile(name string, file *ast.File) { On 2010/12/08 21:33:28, rsc1 wrote: > I think much of this can go away if you use ast.Walk. doesn't really seem much of an improvement to go that way. i still need to write lots of fiddly bits. i like it as is. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:340: "Printf": 0, "Println": 0, On 2010/12/08 21:33:28, rsc1 wrote: > s/f// > .+1s/f// oops. i bet another CL is coming http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:361: arg := call.Args[skip] On 2010/12/08 21:33:28, rsc1 wrote: > check len(call.Args) check it how? http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:373: f.Badf(call.Pos(), "no formatting directive in %s call", name) On 2010/12/08 21:33:28, rsc1 wrote: > I don't think this is bad. > Programs that, say, use Printf consistently seem fine. > it's bad if you have more than one argument, which is what this checking. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:397: var percent = []byte{'%'} On 2010/12/08 21:33:28, rsc1 wrote: > can use IndexByte below instead Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:405: args := call.Args On 2010/12/08 21:33:28, rsc1 wrote: > check len(call.Args) check it how? http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:408: f.Badf(call.Pos(), "no args in %s call", name) On 2010/12/08 21:33:28, rsc1 wrote: > I don't think this is worth complaining about > until the code can distinction fmt.Print() from log.Print() Done. http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:415: f.Badf(call.Pos(), "formatting directive in %s call", name) On 2010/12/08 21:33:28, rsc1 wrote: > s/formatting/possible & Done.
Sign in to reply to this message.
Hello rsc, gri (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:361: arg := call.Args[skip] On 2010/12/08 21:46:38, r wrote: > On 2010/12/08 21:33:28, rsc1 wrote: > > check len(call.Args) > > check it how? if len(call.Args) <= skip { http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:405: args := call.Args On 2010/12/08 21:46:38, r wrote: > On 2010/12/08 21:33:28, rsc1 wrote: > > check len(call.Args) > > check it how? Never mind on this one.
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/1/src/cmd/gocheck/gocheck.go#newco... src/cmd/gocheck/gocheck.go:161: func (f *File) checkFile(name string, file *ast.File) { On 2010/12/08 21:46:38, r wrote: > On 2010/12/08 21:33:28, rsc1 wrote: > > I think much of this can go away if you use ast.Walk. > > doesn't really seem much of an improvement to go that way. i still need to write > lots of fiddly bits. i like it as is. you can pass an *ast.File to ast.Walk and then in the walker look for *ast.CallExpr and call your checkCallExpr. if you did that, checkFile checkDecl checkFuncDecl checkBlock checkStmtList checkStmt checkExprList checkExpr would all just disappear. that's 150 lines that won't need maintenance if something other than the form of a call expression changes. it seems like a big deal.
Sign in to reply to this message.
Some comments. Will look at it again more precisely later. http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:28: func Usage() { s/Usage/usage/ ? http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:37: fs *token.FileSet if you are only operating on a single file, use file *token.File instead. It also supports a Position function and it's more efficient (if you think it may change to multiple files, keep the fileset - either way it's easy to change) http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:79: fs := token.NewFileSet() I'd use a global fset. If you call doFile multiple times there's no need to re-allocate a new fset every single time. In fact, if you use a global fset, you may not need the per file data structure. http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:80: fs.AddFile(name, fs.Base(), 1e6) // TODO: how big should the size argument be? this is not needed - the parser adds the file to the file set (maybe it shouldn't, but that's how it is now) it will read the entire file into memory and then know the size for AddFile http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:85: file := &File{fs} You may not need this. If you want to keep it (no global fset); or if you want to keep track of the per-file *token.File (a bit faster Position function than the one on fset), then write: file := &File{fset.File(parsedFile.Pos())} (This will take a legal position in the parsedFile - the position of the packake keyword - and get the corresponding file back. Since the parser does the AddFile internally, and it doesn't return it explicitly, not store it in the AST, this is a simple mechanism to get it back). http://codereview.appspot.com/3522041/diff/15001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:173: func (f *File) checkStmt(stmt ast.Stmt) { Instead of writing all this tree traversal yourself, why not use the ast.Walk function and just implement the few cases you actually need? It will take care of the right nil checks etc. (Note: I am in the middle of fixing a bug in ast.Walk, but the interface should remain the same). This may cut away a lot of code. There's also ast.Inspect with a slightly simpler interface.
Sign in to reply to this message.
Hello rsc, gri (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
I did the rewrite. It's cleaner code; it's also 50% slower, which is interesting. Gri?? -rob
Sign in to reply to this message.
Hi Rob, If possible, I'd appreciate if another name was selected for the tool. gocheck is being developed for several months, and was already announced and commented upon in the mailing list: http://labix.org/gocheck http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go http://launchpad.net/gocheck
Sign in to reply to this message.
How about golint? - gri On Wed, Dec 8, 2010 at 2:37 PM, <n13m3y3r@gmail.com> wrote: > Hi Rob, > > If possible, I'd appreciate if another name was selected for the tool. > > gocheck is being developed for several months, and was already announced > and commented upon in the mailing list: > > http://labix.org/gocheck > http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go > http://launchpad.net/gocheck > > > http://codereview.appspot.com/3522041/ >
Sign in to reply to this message.
lint was a total piece of crap with horrible properties that corrupted programmers for a generation. golint is an obvious name but i can't bear to associate this program with that one. moreover, lint did vastly more than gocheck, and more than gocheck should or will since we have types and a decent compiler, so i don't want people to think about them together. finally, the joke in lint's name always bothered me. otherwise, a fine suggestion. -rob
Sign in to reply to this message.
> otherwise, a fine suggestion. golint goverify gotest --check goguard gostatic gowell gopure gosafe gofit If you need more, please let me know. Let's just avoid the conflict, please.
Sign in to reply to this message.
n13m3y3r@gmail.com writes: >> otherwise, a fine suggestion. > > golint > goverify > gotest --check > goguard > gostatic > gowell > gopure > gosafe > gofit Or make it an option for gofmt. Ian
Sign in to reply to this message.
On Wed, Dec 8, 2010 at 5:52 PM, Ian Lance Taylor <iant@google.com> wrote: > n13m3y3r@gmail.com writes: > >>> otherwise, a fine suggestion. >> >> golint >> goverify >> gotest --check >> goguard >> gostatic >> gowell >> gopure >> gosafe >> gofit > > Or make it an option for gofmt. > > Ian > gofmt is already pretty heavily burdened. i was thinking this could take some of the load off. it's a tiny program that can expand as needed. but it does make sense to fold it in. -rob
Sign in to reply to this message.
oh that thing. dammit. -rob
Sign in to reply to this message.
Hello rsc, gri, niemeyer, iant2 (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
PTAL while we consider throwing it all away. -rob
Sign in to reply to this message.
on further thought, gofmt doesn't seem like a good match. its job is not to warn about problems but to reformat the code. what would gofmt do if it found an error? and it can't be automatic because this program doesn't (and can't) do much semantic or dynamic stuff; it's all simple static pattern matches. i believe it makes sense to have a separate tool with potentially expensive yet inaccurate checks for sanity. i just need a name. -rob
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/33001/src/cmd/gocheck/gocheck.go File src/cmd/gocheck/gocheck.go (right): http://codereview.appspot.com/3522041/diff/33001/src/cmd/gocheck/gocheck.go#n... src/cmd/gocheck/gocheck.go:147: return f I think you ought to be able to speed this up: Whenever you have a node where you know that it cannot _contain_ a call (all decls except for function decls) you can return nil as result. This will prevent that subtree from being visited. As it is, the entire tree is traversed even where it makes no sense. This may explain the slowdown to some extent.
Sign in to reply to this message.
agreed - I don't want gofmt to become the kitchen sink for everything source code related gosane? - gri On Wed, Dec 8, 2010 at 3:11 PM, Rob 'Commander' Pike <r@golang.org> wrote: > on further thought, gofmt doesn't seem like a good match. its job is > not to warn about problems but to reformat the code. what would gofmt > do if it found an error? and it can't be automatic because this > program doesn't (and can't) do much semantic or dynamic stuff; it's > all simple static pattern matches. > > i believe it makes sense to have a separate tool with potentially > expensive yet inaccurate checks for sanity. > > i just need a name. > > -rob >
Sign in to reply to this message.
what about "gowarn"? i.e. a tool that gives you the warnings that the compiler does not. On 8 December 2010 23:11, Rob 'Commander' Pike <r@golang.org> wrote: > on further thought, gofmt doesn't seem like a good match. its job is > not to warn about problems but to reformat the code. what would gofmt > do if it found an error? and it can't be automatic because this > program doesn't (and can't) do much semantic or dynamic stuff; it's > all simple static pattern matches. > > i believe it makes sense to have a separate tool with potentially > expensive yet inaccurate checks for sanity. > > i just need a name. > > -rob >
Sign in to reply to this message.
Hello rsc, gri, niemeyer, iant2, rog (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
Hello rsc, gri, niemeyer, iant2, rog (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
gocop? .net has 'fxcop' which performs static analysis, seems like a fair analogy! On 8 December 2010 23:12, Robert Griesemer <gri@golang.org> wrote: > agreed - I don't want gofmt to become the kitchen sink for everything source > code related > gosane? > - gri > > On Wed, Dec 8, 2010 at 3:11 PM, Rob 'Commander' Pike <r@golang.org> wrote: >> >> on further thought, gofmt doesn't seem like a good match. its job is >> not to warn about problems but to reformat the code. what would gofmt >> do if it found an error? and it can't be automatic because this >> program doesn't (and can't) do much semantic or dynamic stuff; it's >> all simple static pattern matches. >> >> i believe it makes sense to have a separate tool with potentially >> expensive yet inaccurate checks for sanity. >> >> i just need a name. >> >> -rob > > -- Lorenzo Stoakes http://www.codegrunt.co.uk
Sign in to reply to this message.
i chose 'govet', since it vets the code. that is the end of the naming discussion. -rob
Sign in to reply to this message.
> i chose 'govet', since it vets the code. > > that is the end of the naming discussion. Phew. Thanks! I'm glad we can all go to the vet now. Oh, wait.. crap.
Sign in to reply to this message.
LGTM http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/doc.go File src/cmd/govet/doc.go (right): http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/doc.go#newcode29 src/cmd/govet/doc.go:29: is zero-indexed argument position of the first argument s/is/is the/ http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/doc.go#newcode29 src/cmd/govet/doc.go:29: is zero-indexed argument position of the first argument also should it be "zero-based" ? Not sure what zero-indexed means. http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/doc.go#newcode31 src/cmd/govet/doc.go:31: arguemnt for non-formatted prints. s/arguemnt/argument/ http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/doc.go#newcode31 src/cmd/govet/doc.go:31: arguemnt for non-formatted prints. perhaps an example using fmt.Printf? http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/govet.go File src/cmd/govet/govet.go (right): http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/govet.go#newco... src/cmd/govet/govet.go:72: } It would be nice if it could operate on directories like gofmt. Maybe another CL. http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/govet.go#newco... src/cmd/govet/govet.go:145: f.checkCallExpr(n) add a TODO: should return nil for nodes that cannot contain a CallExpr - will shortcut traversal http://codereview.appspot.com/3522041/diff/46001/src/cmd/govet/govet.go#newco... src/cmd/govet/govet.go:237: var terminalNewline = []byte{'\\', 'n', '"'} // \n at end of interpreted string []byte(`\n"`) ?
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/57001/src/cmd/govet/govet.go File src/cmd/govet/govet.go (right): http://codereview.appspot.com/3522041/diff/57001/src/cmd/govet/govet.go#newco... src/cmd/govet/govet.go:27: // If --help is set, it prints a longer description. Delete because --help is gone.
Sign in to reply to this message.
http://codereview.appspot.com/3522041/diff/63001/src/cmd/make.bash File src/cmd/make.bash (right): http://codereview.appspot.com/3522041/diff/63001/src/cmd/make.bash#newcode24 src/cmd/make.bash:24: for i in cc ${O}l ${O}a ${O}c gc ${O}g cov godefs gopack gotest govet nm prof this needs to be removed and rather have something like: diff -r a5eebdd09522 src/pkg/Makefile --- a/src/pkg/Makefile Wed Dec 08 21:36:56 2010 -0800 +++ b/src/pkg/Makefile Wed Dec 08 22:49:14 2010 -0800 @@ -139,6 +139,7 @@ ../cmd/goinstall\ ../cmd/goyacc\ ../cmd/hgpatch\ + ../cmd/govet\ NOTEST=\ debug/proc\
Sign in to reply to this message.
Hello rsc, gri, niemeyer, iant2, rog, lstoakes, jacek.masiulaniec@gmail.com, cw (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
LGTM
Sign in to reply to this message.
*** Submitted as http://code.google.com/p/go/source/detail?r=752e82357e09 *** govet: a new static checker for Go programs. At the moment, and for the forseeable future, it only checks arguments to print calls. R=rsc, gri, niemeyer, iant2, rog, lstoakes, jacek.masiulaniec, cw CC=golang-dev http://codereview.appspot.com/3522041
Sign in to reply to this message.
|