func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error {
	fileTree, err := goparser.ParseFile(token.NewFileSet(), mainAPIFile, nil, goparser.ParseComments)
	if err != nil {
		return fmt.Errorf("cannot parse source files %s: %s", mainAPIFile, err)
	}
	parser.swagger.Swagger = "2.0"
	for _, comment := range fileTree.Comments {
		comments := strings.Split(comment.Text(), "\n")
		if !isGeneralAPIComment(comments) {
			continue
		}
		err := parseGeneralAPIInfo(parser, comments)
		if err != nil {
			return err
		}
	}
	return nil
}
ParseGeneralAPIInfo parses general api info for given mainAPIFile path.
package swag
import (
	"encoding/json"
	"errors"
	"fmt"
	"go/ast"
	"go/build"
	goparser "go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"unicode"
	"github.com/KyleBanks/depth"
	"github.com/go-openapi/spec"
)
const (
	CamelCase = "camelcase"
	PascalCase = "pascalcase"
	SnakeCase = "snakecase"
	acceptAttr      = "@accept"
	produceAttr     = "@produce"
	scopeAttrPrefix = "@scope."
)
var (
	ErrRecursiveParseStruct = errors.New("recursively parsing struct")
	ErrFuncTypeField = errors.New("field type is func")
	ErrFailedConvertPrimitiveType = errors.New("swag property: failed convert primitive type")
)
type Parser struct {
	swagger *spec.Swagger
	packages *PackagesDefinitions
	parsedSchemas map[*TypeSpecDef]*Schema
	outputSchemas map[*TypeSpecDef]*Schema
	existSchemaNames map[string]*Schema
	toBeRenamedSchemas map[string]string
	toBeRenamedRefURLs []*url.URL
	PropNamingStrategy string
	ParseVendor bool
	ParseDependency bool
	ParseInternal bool
	Strict bool
	structStack []*TypeSpecDef
	markdownFileDir string
	codeExampleFilesDir string
	collectionFormatInQuery string
	excludes map[string]bool
	debug Debugger
}
type Debugger interface {
	Printf(format string, v ...interface{})
}
func New(options ...func(*Parser)) *Parser {
	parser := &Parser{
		swagger: &spec.Swagger{
			SwaggerProps: spec.SwaggerProps{
				Info: &spec.Info{
					InfoProps: spec.InfoProps{
						Contact: &spec.ContactInfo{},
						License: nil,
					},
					VendorExtensible: spec.VendorExtensible{
						Extensions: spec.Extensions{},
					},
				},
				Paths: &spec.Paths{
					Paths: make(map[string]spec.PathItem),
				},
				Definitions:         make(map[string]spec.Schema),
				SecurityDefinitions: make(map[string]*spec.SecurityScheme),
			},
		},
		packages:           NewPackagesDefinitions(),
		debug:              log.New(os.Stdout, "", log.LstdFlags),
		parsedSchemas:      make(map[*TypeSpecDef]*Schema),
		outputSchemas:      make(map[*TypeSpecDef]*Schema),
		existSchemaNames:   make(map[string]*Schema),
		toBeRenamedSchemas: make(map[string]string),
		excludes:           make(map[string]bool),
	}
	for _, option := range options {
		option(parser)
	}
	return parser
}
func SetMarkdownFileDirectory(directoryPath string) func(*Parser) {
	return func(p *Parser) {
		p.markdownFileDir = directoryPath
	}
}
func SetCodeExamplesDirectory(directoryPath string) func(*Parser) {
	return func(p *Parser) {
		p.codeExampleFilesDir = directoryPath
	}
}
func SetExcludedDirsAndFiles(excludes string) func(*Parser) {
	return func(p *Parser) {
		for _, f := range strings.Split(excludes, ",") {
			f = strings.TrimSpace(f)
			if f != "" {
				f = filepath.Clean(f)
				p.excludes[f] = true
			}
		}
	}
}
func SetStrict(strict bool) func(*Parser) {
	return func(p *Parser) {
		p.Strict = strict
	}
}
func SetDebugger(logger Debugger) func(parser *Parser) {
	return func(p *Parser) {
		p.debug = logger
	}
}
func (parser *Parser) ParseAPI(searchDir string, mainAPIFile string, parseDepth int) error {
	return parser.ParseAPIMultiSearchDir([]string{searchDir}, mainAPIFile, parseDepth)
}
func (parser *Parser) ParseAPIMultiSearchDir(searchDirs []string, mainAPIFile string, parseDepth int) error {
	for _, searchDir := range searchDirs {
		parser.debug.Printf("Generate general API Info, search dir:%s", searchDir)
		packageDir, err := getPkgName(searchDir)
		if err != nil {
			parser.debug.Printf("warning: failed to get package name in dir: %s, error: %s", searchDir, err.Error())
		}
		err = parser.getAllGoFileInfo(packageDir, searchDir)
		if err != nil {
			return err
		}
	}
	absMainAPIFilePath, err := filepath.Abs(filepath.Join(searchDirs[0], mainAPIFile))
	if err != nil {
		return err
	}
	if parser.ParseDependency {
		var t depth.Tree
		t.ResolveInternal = true
		t.MaxDepth = parseDepth
		pkgName, err := getPkgName(filepath.Dir(absMainAPIFilePath))
		if err != nil {
			return err
		}
		err = t.Resolve(pkgName)
		if err != nil {
			return fmt.Errorf("pkg %s cannot find all dependencies, %s", pkgName, err)
		}
		for i := 0; i < len(t.Root.Deps); i++ {
			err := parser.getAllGoFileInfoFromDeps(&t.Root.Deps[i])
			if err != nil {
				return err
			}
		}
	}
	err = parser.ParseGeneralAPIInfo(absMainAPIFilePath)
	if err != nil {
		return err
	}
	parser.parsedSchemas, err = parser.packages.ParseTypes()
	if err != nil {
		return err
	}
	err = parser.packages.RangeFiles(parser.ParseRouterAPIInfo)
	if err != nil {
		return err
	}
	parser.renameRefSchemas()
	return parser.checkOperationIDUniqueness()
}
func getPkgName(searchDir string) (string, error) {
	cmd := exec.Command("go", "list", "-f={{.ImportPath}}")
	cmd.Dir = searchDir
	var stdout, stderr strings.Builder
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("execute go list command, %s, stdout:%s, stderr:%s", err, stdout.String(), stderr.String())
	}
	outStr, _ := stdout.String(), stderr.String()
	if outStr[0] == '_' {  
		outStr = strings.TrimPrefix(outStr, "_"+build.Default.GOPATH+"/src/")
	}
	f := strings.Split(outStr, "\n")
	outStr = f[0]
	return outStr, nil
}
func initIfEmpty(license *spec.License) *spec.License {
	if license == nil {
		return new(spec.License)
	}
	return license
}