// Copyright 2014 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 ( "go/ast" "go/build" "go/parser" "go/scanner" "go/token" "go/types" "io" "os" "path/filepath" "unicode" "unicode/utf8" "golang.org/x/mobile/bind" "golang.org/x/mobile/internal/loader" ) func genPkg(pkg *build.Package) { files := parseFiles(pkg.Dir, pkg.GoFiles) if len(files) == 0 { return // some error has been reported } conf := loader.Config{ Fset: fset, AllowErrors: true, } conf.TypeChecker.IgnoreFuncBodies = true conf.TypeChecker.FakeImportC = true conf.TypeChecker.DisableUnusedImportCheck = true var tcErrs []error conf.TypeChecker.Error = func(err error) { tcErrs = append(tcErrs, err) } conf.CreateFromFiles(pkg.ImportPath, files...) program, err := conf.Load() if err != nil { for _, err := range tcErrs { errorf("%v", err) } errorf("%v", err) return } p := program.Created[0].Pkg fname := defaultFileName(*lang, p) switch *lang { case "java": w, closer := writer(fname, p) processErr(bind.GenJava(w, fset, p, *javaPkg)) closer() case "go": w, closer := writer(fname, p) processErr(bind.GenGo(w, fset, p)) closer() case "objc": if fname == "" { processErr(bind.GenObjc(os.Stdout, fset, p, *prefix, true)) processErr(bind.GenObjc(os.Stdout, fset, p, *prefix, false)) } else { hname := fname[:len(fname)-2] + ".h" w, closer := writer(hname, p) processErr(bind.GenObjc(w, fset, p, *prefix, true)) closer() w, closer = writer(fname, p) processErr(bind.GenObjc(w, fset, p, *prefix, false)) closer() } default: errorf("unknown target language: %q", *lang) } } func processErr(err error) { if err != nil { if list, _ := err.(bind.ErrorList); len(list) > 0 { for _, err := range list { errorf("%v", err) } } else { errorf("%v", err) } } } var fset = token.NewFileSet() func parseFiles(dir string, filenames []string) []*ast.File { var files []*ast.File hasErr := false for _, filename := range filenames { path := filepath.Join(dir, filename) file, err := parser.ParseFile(fset, path, nil, parser.AllErrors) if err != nil { hasErr = true if list, _ := err.(scanner.ErrorList); len(list) > 0 { for _, err := range list { errorf("%v", err) } } else { errorf("%v", err) } } files = append(files, file) } if hasErr { return nil } return files } func writer(fname string, pkg *types.Package) (w io.Writer, closer func()) { if fname == "" { return os.Stdout, func() { return } } dir := filepath.Dir(fname) if err := os.MkdirAll(dir, 0755); err != nil { errorf("invalid output dir: %v", err) os.Exit(exitStatus) } f, err := os.Create(fname) if err != nil { errorf("invalid output dir: %v", err) os.Exit(exitStatus) } closer = func() { if err := f.Close(); err != nil { errorf("error in closing output file: %v", err) } } return f, closer } func defaultFileName(lang string, pkg *types.Package) string { if *outdir == "" { return "" } switch lang { case "java": firstRune, size := utf8.DecodeRuneInString(pkg.Name()) className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:] return filepath.Join(*outdir, className+".java") case "go": return filepath.Join(*outdir, "go_"+pkg.Name()+".go") case "objc": firstRune, size := utf8.DecodeRuneInString(pkg.Name()) className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:] return filepath.Join(*outdir, "Go"+className+".m") } errorf("unknown target language: %q", lang) os.Exit(exitStatus) return "" }