Ejemplo n.º 1
0
func TestContainingPackage(t *testing.T) {
	// unvirtualized:
	goroot := runtime.GOROOT()
	gopath := filepath.SplitList(os.Getenv("GOPATH"))[0]

	for _, test := range [][2]string{
		{goroot + "/src/fmt/print.go", "fmt"},
		{goroot + "/src/encoding/json/foo.go", "encoding/json"},
		{goroot + "/src/encoding/missing/foo.go", "(not found)"},
		{gopath + "/src/golang.org/x/tools/go/buildutil/util_test.go",
			"golang.org/x/tools/go/buildutil"},
	} {
		file, want := test[0], test[1]
		bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
		got := bp.ImportPath
		if err != nil {
			got = "(not found)"
		}
		if got != want {
			t.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
		}
	}

	// TODO(adonovan): test on virtualized GOPATH too.
}
Ejemplo n.º 2
0
// Run is a wrapper for the gogetdoc command.  It is broken out of main for easier testing.
func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.New("gogetdoc: couldn't get working directory")
	}
	bp, err := buildutil.ContainingPackage(ctx, wd, filename)
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
	}
	conf := &loader.Config{
		Build:               ctx,
		ParserMode:          parser.ParseComments,
		TypeCheckFuncBodies: func(pkg string) bool { return pkg == bp.ImportPath },
		AllowErrors:         true,
	}

	var parseError error
	conf.TypeChecker.Error = func(err error) {
		if parseError != nil {
			return
		}
		parseError = err
	}
	conf.ImportWithTests(bp.ImportPath)
	lprog, err := conf.Load()
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: error loading program: %s", err.Error())
	}
	doc, err := DocForPos(ctx, lprog, filename, offset)
	if err != nil && parseError != nil {
		fmt.Fprintln(os.Stderr, parseError)
	}
	return doc, err
}
Ejemplo n.º 3
0
func TestContainingPackage(t *testing.T) {
	// unvirtualized:
	goroot := runtime.GOROOT()
	gopath := filepath.SplitList(os.Getenv("GOPATH"))[0]

	tests := [][2]string{
		{goroot + "/src/fmt/print.go", "fmt"},
		{goroot + "/src/encoding/json/foo.go", "encoding/json"},
		{goroot + "/src/encoding/missing/foo.go", "(not found)"},
		{gopath + "/src/golang.org/x/tools/go/buildutil/util_test.go",
			"golang.org/x/tools/go/buildutil"},
	}
	// TODO(adonovan): simplify after Go 1.6.
	if buildutil.AllowVendor != 0 {
		tests = append(tests, [2]string{
			gopath + "/src/vendor/golang.org/x/net/http2/hpack/hpack.go",
			"vendor/golang.org/x/net/http2/hpack",
		})
	}
	for _, test := range tests {
		file, want := test[0], test[1]
		bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
		got := bp.ImportPath
		if err != nil {
			got = "(not found)"
		}
		if got != want {
			t.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
		}
	}

	// TODO(adonovan): test on virtualized GOPATH too.
}
Ejemplo n.º 4
0
func testContainingPackageCaseFold(file, want string) error {
	bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
	if err != nil {
		return err
	}
	if got := bp.ImportPath; got != want {
		return fmt.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
	}
	return nil
}
Ejemplo n.º 5
0
// parseOffsetFlag interprets the "-offset" flag value as a renaming specification.
func parseOffsetFlag(ctxt *build.Context, offsetFlag string) (*spec, error) {
	var spec spec
	// Validate -offset, e.g. file.go:#123
	parts := strings.Split(offsetFlag, ":#")
	if len(parts) != 2 {
		return nil, fmt.Errorf("-offset %q: invalid offset specification", offsetFlag)
	}

	spec.filename = parts[0]
	if !buildutil.FileExists(ctxt, spec.filename) {
		return nil, fmt.Errorf("no such file: %s", spec.filename)
	}

	bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
	if err != nil {
		return nil, err
	}
	spec.pkg = bp.ImportPath

	for _, r := range parts[1] {
		if !isDigit(r) {
			return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
		}
	}
	spec.offset, err = strconv.Atoi(parts[1])
	if err != nil {
		return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
	}

	// Parse the file and check there's an identifier at that offset.
	fset := token.NewFileSet()
	f, err := buildutil.ParseFile(fset, ctxt, nil, wd, spec.filename, parser.ParseComments)
	if err != nil {
		return nil, fmt.Errorf("-offset %q: cannot parse file: %s", offsetFlag, err)
	}

	id := identAtOffset(fset, f, spec.offset)
	if id == nil {
		return nil, fmt.Errorf("-offset %q: no identifier at this position", offsetFlag)
	}

	spec.fromName = id.Name

	return &spec, nil
}
Ejemplo n.º 6
0
// parseFromFlag interprets the "-from" flag value as a renaming specification.
// See Usage in rename.go for valid formats.
func parseFromFlag(ctxt *build.Context, fromFlag string) (*spec, error) {
	var spec spec
	var main string // sans "::x" suffix
	switch parts := strings.Split(fromFlag, "::"); len(parts) {
	case 1:
		main = parts[0]
	case 2:
		main = parts[0]
		spec.searchFor = parts[1]
		if parts[1] == "" {
			// error
		}
	default:
		return nil, fmt.Errorf("-from %q: invalid identifier specification (see -help for formats)", fromFlag)
	}

	if strings.HasSuffix(main, ".go") {
		// main is "filename.go"
		if spec.searchFor == "" {
			return nil, fmt.Errorf("-from: filename %q must have a ::name suffix", main)
		}
		spec.filename = main
		if !buildutil.FileExists(ctxt, spec.filename) {
			return nil, fmt.Errorf("no such file: %s", spec.filename)
		}

		bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
		if err != nil {
			return nil, err
		}
		spec.pkg = bp.ImportPath

	} else {
		// main is one of:
		//  "importpath"
		//  "importpath".member
		//  (*"importpath".type).fieldormethod           (parens and star optional)
		if err := parseObjectSpec(&spec, main); err != nil {
			return nil, err
		}
	}

	if spec.searchFor != "" {
		spec.fromName = spec.searchFor
	}

	cwd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	// Sanitize the package.
	bp, err := ctxt.Import(spec.pkg, cwd, build.FindOnly)
	if err != nil {
		return nil, fmt.Errorf("can't find package %q", spec.pkg)
	}
	spec.pkg = bp.ImportPath

	if !isValidIdentifier(spec.fromName) {
		return nil, fmt.Errorf("-from: invalid identifier %q", spec.fromName)
	}

	if Verbose {
		log.Printf("-from spec: %+v", spec)
	}

	return &spec, nil
}