Example #1
0
// errorOrVoid filters the list of functions to only those that return only an
// error or have no return value.
func errorOrVoid(fns []*ast.FuncDecl, info types.Info) []*ast.FuncDecl {
	fds := []*ast.FuncDecl{}

	for _, fn := range fns {
		// look for functions with 0 or 1 return values
		res := fn.Type.Results
		if res.NumFields() > 1 {
			continue
		}
		// 0 return value is ok
		if res.NumFields() == 0 {
			fds = append(fds, fn)
			continue
		}
		// if 1 return value, look for those that return an error
		ret := res.List[0]

		// handle (a, b, c int)
		if len(ret.Names) > 1 {
			continue
		}
		t := info.TypeOf(ret.Type)
		if t != nil && t.String() == "error" {
			fds = append(fds, fn)
		}
	}
	return fds
}
Example #2
0
func functions(f *ast.File, info types.Info, fset *token.FileSet) ([]Function, error) {
	fns := exportedFuncs(f, fset)
	fns = errorOrVoid(fns, info)

	cmtMap := ast.NewCommentMap(fset, f, f.Comments)

	functions := make([]Function, len(fns))

	for i, fn := range fns {
		fun := Function{Name: fn.Name.Name}
		fun.Comment = combine(cmtMap[fn])

		// we only support null returns or error returns, so if there's a
		// return, it's an error.
		if len(fn.Type.Results.List) > 0 {
			fun.IsError = true
		}
		params := fn.Type.Params.List
		fun.Params = make([]Param, 0, len(params))
		for _, field := range params {
			t := info.TypeOf(field.Type)
			pointer := false
			if p, ok := t.(*types.Pointer); ok {
				t = p.Elem()
				pointer = true
			}
			if b, ok := t.(*types.Basic); ok {
				if b.Kind() == types.UnsafePointer {
					log.Printf(
						"Can't create command for function %q because its parameter %q is an unsafe.Pointer.",
						fn.Name.Name,
						field.Names[0])
					break
				}

				fieldCmt := combine(cmtMap[field])
				// handle a, b, c int
				for _, name := range field.Names {
					nameCmt := combine(cmtMap[name])
					if nameCmt == "" {
						nameCmt = fieldCmt
					}
					param := Param{
						Name:      name.Name,
						Type:      b.Kind(),
						IsPointer: pointer,
						Comment:   nameCmt,
					}
					fun.Params = append(fun.Params, param)
				}
				continue
			}
		}
		functions[i] = fun
	}
	return functions, nil
}