2014-08-01 10:45:18 -04:00
|
|
|
// 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"
|
2015-07-25 09:45:10 -04:00
|
|
|
"go/types"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"unicode"
|
|
|
|
"unicode/utf8"
|
2014-08-01 10:45:18 -04:00
|
|
|
|
2014-11-10 08:55:57 +11:00
|
|
|
"golang.org/x/mobile/bind"
|
2015-07-25 09:45:10 -04:00
|
|
|
"golang.org/x/mobile/internal/loader"
|
2014-08-01 10:45:18 -04:00
|
|
|
)
|
|
|
|
|
2015-02-06 18:24:35 -05:00
|
|
|
func genPkg(pkg *build.Package) {
|
2014-08-01 10:45:18 -04:00
|
|
|
files := parseFiles(pkg.Dir, pkg.GoFiles)
|
|
|
|
if len(files) == 0 {
|
|
|
|
return // some error has been reported
|
|
|
|
}
|
|
|
|
|
2014-08-12 14:09:08 -04:00
|
|
|
conf := loader.Config{
|
2015-07-25 09:45:10 -04:00
|
|
|
Fset: fset,
|
|
|
|
AllowErrors: true,
|
2014-08-12 14:09:08 -04:00
|
|
|
}
|
2015-07-25 09:45:10 -04:00
|
|
|
conf.TypeChecker.IgnoreFuncBodies = true
|
|
|
|
conf.TypeChecker.FakeImportC = true
|
|
|
|
conf.TypeChecker.DisableUnusedImportCheck = true
|
|
|
|
var tcErrs []error
|
2014-08-12 14:09:08 -04:00
|
|
|
conf.TypeChecker.Error = func(err error) {
|
2015-07-25 09:45:10 -04:00
|
|
|
tcErrs = append(tcErrs, err)
|
2014-08-01 10:45:18 -04:00
|
|
|
}
|
2014-08-12 14:09:08 -04:00
|
|
|
conf.CreateFromFiles(pkg.ImportPath, files...)
|
|
|
|
program, err := conf.Load()
|
2014-08-01 10:45:18 -04:00
|
|
|
if err != nil {
|
2015-07-25 09:45:10 -04:00
|
|
|
for _, err := range tcErrs {
|
|
|
|
errorf("%v", err)
|
|
|
|
}
|
2014-08-12 14:09:08 -04:00
|
|
|
errorf("%v", err)
|
|
|
|
return
|
2014-08-01 10:45:18 -04:00
|
|
|
}
|
2014-08-12 14:09:08 -04:00
|
|
|
p := program.Created[0].Pkg
|
2014-08-01 10:45:18 -04:00
|
|
|
|
2015-06-07 14:02:07 -04:00
|
|
|
fname := defaultFileName(*lang, p)
|
2014-08-01 10:45:18 -04:00
|
|
|
switch *lang {
|
|
|
|
case "java":
|
2015-06-07 14:02:07 -04:00
|
|
|
w, closer := writer(fname, p)
|
2015-08-27 12:19:47 -04:00
|
|
|
processErr(bind.GenJava(w, fset, p, *javaPkg))
|
2015-06-07 14:02:07 -04:00
|
|
|
closer()
|
2014-08-01 10:45:18 -04:00
|
|
|
case "go":
|
2015-06-07 14:02:07 -04:00
|
|
|
w, closer := writer(fname, p)
|
|
|
|
processErr(bind.GenGo(w, fset, p))
|
|
|
|
closer()
|
|
|
|
case "objc":
|
|
|
|
if fname == "" {
|
2015-08-27 12:19:47 -04:00
|
|
|
processErr(bind.GenObjc(os.Stdout, fset, p, *prefix, true))
|
|
|
|
processErr(bind.GenObjc(os.Stdout, fset, p, *prefix, false))
|
2015-06-07 14:02:07 -04:00
|
|
|
} else {
|
|
|
|
hname := fname[:len(fname)-2] + ".h"
|
|
|
|
w, closer := writer(hname, p)
|
2015-08-27 12:19:47 -04:00
|
|
|
processErr(bind.GenObjc(w, fset, p, *prefix, true))
|
2015-06-07 14:02:07 -04:00
|
|
|
closer()
|
|
|
|
w, closer = writer(fname, p)
|
2015-08-27 12:19:47 -04:00
|
|
|
processErr(bind.GenObjc(w, fset, p, *prefix, false))
|
2015-06-07 14:02:07 -04:00
|
|
|
closer()
|
|
|
|
}
|
2014-08-01 10:45:18 -04:00
|
|
|
default:
|
|
|
|
errorf("unknown target language: %q", *lang)
|
|
|
|
}
|
2015-06-07 14:02:07 -04:00
|
|
|
}
|
2014-08-01 10:45:18 -04:00
|
|
|
|
2015-06-07 14:02:07 -04:00
|
|
|
func processErr(err error) {
|
2014-08-01 10:45:18 -04:00
|
|
|
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
|
|
|
|
}
|
2015-02-06 18:24:35 -05:00
|
|
|
|
2015-06-07 14:02:07 -04:00
|
|
|
func writer(fname string, pkg *types.Package) (w io.Writer, closer func()) {
|
|
|
|
if fname == "" {
|
|
|
|
return os.Stdout, func() { return }
|
2015-02-06 18:24:35 -05:00
|
|
|
}
|
|
|
|
|
2015-06-07 14:02:07 -04:00
|
|
|
dir := filepath.Dir(fname)
|
|
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
|
|
errorf("invalid output dir: %v", err)
|
|
|
|
os.Exit(exitStatus)
|
2015-02-06 18:24:35 -05:00
|
|
|
}
|
2015-06-07 14:02:07 -04:00
|
|
|
|
|
|
|
f, err := os.Create(fname)
|
2015-02-06 18:24:35 -05:00
|
|
|
if err != nil {
|
2015-06-07 14:02:07 -04:00
|
|
|
errorf("invalid output dir: %v", err)
|
|
|
|
os.Exit(exitStatus)
|
2015-02-06 18:24:35 -05:00
|
|
|
}
|
2015-06-07 14:02:07 -04:00
|
|
|
closer = func() {
|
|
|
|
if err := f.Close(); err != nil {
|
|
|
|
errorf("error in closing output file: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return f, closer
|
2015-02-06 18:24:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func defaultFileName(lang string, pkg *types.Package) string {
|
2015-06-07 14:02:07 -04:00
|
|
|
if *outdir == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-02-06 18:24:35 -05:00
|
|
|
switch lang {
|
|
|
|
case "java":
|
|
|
|
firstRune, size := utf8.DecodeRuneInString(pkg.Name())
|
|
|
|
className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:]
|
2015-06-07 14:02:07 -04:00
|
|
|
return filepath.Join(*outdir, className+".java")
|
2015-02-06 18:24:35 -05:00
|
|
|
case "go":
|
2015-06-07 14:02:07 -04:00
|
|
|
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")
|
2015-02-06 18:24:35 -05:00
|
|
|
}
|
|
|
|
errorf("unknown target language: %q", lang)
|
|
|
|
os.Exit(exitStatus)
|
|
|
|
return ""
|
|
|
|
}
|