Commit c734b50b authored by Robert Griesemer's avatar Robert Griesemer

gotype: clean handling of stdin, added tests

- removed uses of global variables
- minor cleanups

R=r
CC=golang-dev
https://golang.org/cl/4277044
parent 86e35a96
...@@ -9,3 +9,6 @@ GOFILES=\ ...@@ -9,3 +9,6 @@ GOFILES=\
gotype.go\ gotype.go\
include ../../Make.cmd include ../../Make.cmd
test:
gotest
...@@ -55,3 +55,5 @@ To verify the output of a pipe: ...@@ -55,3 +55,5 @@ To verify the output of a pipe:
*/ */
package documentation package documentation
// BUG(gri): At the moment, only single-file scope analysis is performed.
...@@ -30,11 +30,7 @@ var ( ...@@ -30,11 +30,7 @@ var (
) )
var ( var exitCode = 0
fset = token.NewFileSet()
exitCode = 0
parserMode = parser.DeclarationErrors
)
func usage() { func usage() {
...@@ -44,35 +40,21 @@ func usage() { ...@@ -44,35 +40,21 @@ func usage() {
} }
func processFlags() {
flag.Usage = usage
flag.Parse()
if *printTrace {
parserMode |= parser.Trace
}
}
func report(err os.Error) { func report(err os.Error) {
scanner.PrintError(os.Stderr, err) scanner.PrintError(os.Stderr, err)
exitCode = 2 exitCode = 2
} }
// parseFile returns the AST for the given file. // parse returns the AST for the Go source src.
// The result // The filename is for error reporting only.
func parseFile(filename string) *ast.File { // The result is nil if there were errors or if
// the file does not belong to the -p package.
func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
if *verbose { if *verbose {
fmt.Println(filename) fmt.Println(filename)
} }
// get source
src, err := ioutil.ReadFile(filename)
if err != nil {
report(err)
return nil
}
// ignore files with different package name // ignore files with different package name
if *pkgName != "" { if *pkgName != "" {
file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly) file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly)
...@@ -89,7 +71,11 @@ func parseFile(filename string) *ast.File { ...@@ -89,7 +71,11 @@ func parseFile(filename string) *ast.File {
} }
// parse entire file // parse entire file
file, err := parser.ParseFile(fset, filename, src, parserMode) mode := parser.DeclarationErrors
if *printTrace {
mode |= parser.Trace
}
file, err := parser.ParseFile(fset, filename, src, mode)
if err != nil { if err != nil {
report(err) report(err)
return nil return nil
...@@ -102,33 +88,38 @@ func parseFile(filename string) *ast.File { ...@@ -102,33 +88,38 @@ func parseFile(filename string) *ast.File {
} }
// BUG(gri): At the moment, only single-file scope analysis is performed. func parseStdin(fset *token.FileSet) (files map[string]*ast.File) {
files = make(map[string]*ast.File)
src, err := ioutil.ReadAll(os.Stdin)
if err != nil {
report(err)
return
}
const filename = "<standard input>"
if file := parse(fset, filename, src); file != nil {
files[filename] = file
}
return
}
func processPackage(filenames []string) { func parseFiles(fset *token.FileSet, filenames []string) (files map[string]*ast.File) {
var files []*ast.File files = make(map[string]*ast.File)
pkgName := ""
for _, filename := range filenames { for _, filename := range filenames {
file := parseFile(filename) src, err := ioutil.ReadFile(filename)
if file == nil { if err != nil {
continue // ignore file report(err)
continue
} }
// package names must match if file := parse(fset, filename, src); file != nil {
// TODO(gri): this check should be moved into a if files[filename] != nil {
// function making the package below report(os.ErrorString(fmt.Sprintf("%q: duplicate file", filename)))
if pkgName == "" {
// first package file
pkgName = file.Name.Name
} else {
if file.Name.Name != pkgName {
report(os.NewError(fmt.Sprintf("file %q is in package %q not %q", filename, file.Name.Name, pkgName)))
continue continue
} }
files[filename] = file
} }
files = append(files, file)
} }
return
// TODO(gri): make a ast.Package and analyze it
_ = files
} }
...@@ -174,15 +165,31 @@ func processFiles(filenames []string, allFiles bool) { ...@@ -174,15 +165,31 @@ func processFiles(filenames []string, allFiles bool) {
} }
} }
} }
processPackage(filenames[0:i]) processPackage(parseFiles(token.NewFileSet(), filenames[0:i]))
}
func processPackage(files map[string]*ast.File) {
// TODO(gri) Enable this code once we have ast.NewPackage.
/*
// make a package (resolve all identifiers)
pkg, err := ast.NewPackage(files)
if err != nil {
report(err)
return
}
// TODO(gri): typecheck package
_ = pkg
*/
} }
func main() { func main() {
processFlags() flag.Usage = usage
flag.Parse()
if flag.NArg() == 0 { if flag.NArg() == 0 {
processPackage([]string{os.Stdin.Name()}) processPackage(parseStdin(token.NewFileSet()))
} else { } else {
processFiles(flag.Args(), true) processFiles(flag.Args(), true)
} }
......
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"path/filepath"
"runtime"
"testing"
)
func testDir(t *testing.T, dir, pkg string) {
*pkgName = pkg
*recursive = false
processDirectory(dir)
if exitCode != 0 {
t.Errorf("processing %d failed: exitCode = %d", dir, exitCode)
}
}
func Test(t *testing.T) {
testDir(t, ".", "main")
testDir(t, filepath.Join(runtime.GOROOT(), "src/pkg/go/ast"), "ast")
testDir(t, filepath.Join(runtime.GOROOT(), "src/pkg/go/scanner"), "scanner")
testDir(t, filepath.Join(runtime.GOROOT(), "src/pkg/go/parser"), "parser")
}
...@@ -192,7 +192,6 @@ NOTEST=\ ...@@ -192,7 +192,6 @@ NOTEST=\
../cmd/ebnflint\ ../cmd/ebnflint\
../cmd/godoc\ ../cmd/godoc\
../cmd/gofmt\ ../cmd/gofmt\
../cmd/gotype\
../cmd/govet\ ../cmd/govet\
../cmd/goyacc\ ../cmd/goyacc\
../cmd/hgpatch\ ../cmd/hgpatch\
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment