| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Go Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style | |
| 3 // license that can be found in the LICENSE file. | |
| 4 | |
| 5 package bind | |
| 6 | |
| 7 import ( | |
| 8 "bytes" | |
| 9 "fmt" | |
| 10 "go/token" | |
| 11 "io" | |
| 12 "regexp" | |
| 13 "unicode" | |
| 14 "unicode/utf8" | |
| 15 | |
| 16 "golang.org/x/tools/go/types" | |
| 17 ) | |
| 18 | |
| 19 // TODO(crawshaw): disallow basic android java type names in exported symbols. | |
| 20 // TODO(crawshaw): generate all relevant "implements" relationships for interfac
es. | |
| 21 // TODO(crawshaw): consider introducing Java functions for casting to and from i
nterfaces at runtime. | |
| 22 | |
| 23 type ErrorList []error | |
| 24 | |
| 25 func (list ErrorList) Error() string { | |
| 26 buf := new(bytes.Buffer) | |
| 27 for i, err := range list { | |
| 28 if i > 0 { | |
| 29 buf.WriteRune('\n') | |
| 30 } | |
| 31 io.WriteString(buf, err.Error()) | |
| 32 } | |
| 33 return buf.String() | |
| 34 } | |
| 35 | |
| 36 type javaGen struct { | |
| 37 *printer | |
| 38 nextCode int | |
| 39 fset *token.FileSet | |
| 40 pkg *types.Package | |
| 41 err ErrorList | |
| 42 } | |
| 43 | |
| 44 func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) { | |
| 45 fields := exportedFields(T) | |
| 46 methods := exportedMethodSet(types.NewPointer(obj.Type())) | |
| 47 | |
| 48 g.Printf("public static final class %s implements go.Seq.Object {\n", ob
j.Name()) | |
| 49 g.Indent() | |
| 50 g.Printf("private static final String DESCRIPTOR = \"go.%s.%s\";\n", g.p
kg.Name(), obj.Name()) | |
| 51 for i, f := range fields { | |
| 52 g.Printf("private static final int FIELD_%s_GET = 0x%x0f;\n", f.
Name(), i) | |
| 53 g.Printf("private static final int FIELD_%s_SET = 0x%x1f;\n", f.
Name(), i) | |
| 54 } | |
| 55 for i, m := range methods { | |
| 56 g.Printf("private static final int CALL_%s = 0x%x0c;\n", m.Name(
), i) | |
| 57 } | |
| 58 g.Printf("\n") | |
| 59 | |
| 60 g.Printf("private go.Seq.Ref ref;\n\n") | |
| 61 | |
| 62 n := obj.Name() | |
| 63 g.Printf("private %s(go.Seq.Ref ref) { this.ref = ref; }\n\n", n) | |
| 64 g.Printf(`public go.Seq.Ref ref() { return ref; } | |
| 65 | |
| 66 public void call(int code, go.Seq in, go.Seq out) { | |
| 67 throw new RuntimeException("internal error: cycle: cannot call concrete prox
y"); | |
| 68 } | |
| 69 | |
| 70 `) | |
| 71 | |
| 72 for _, f := range fields { | |
| 73 g.Printf("public %s get%s() {\n", g.javaType(f.Type()), f.Name()
) | |
| 74 g.Indent() | |
| 75 g.Printf("Seq in = new Seq();\n") | |
| 76 g.Printf("Seq out = new Seq();\n") | |
| 77 g.Printf("in.writeRef(ref);\n") | |
| 78 g.Printf("Seq.send(DESCRIPTOR, FIELD_%s_GET, in, out);\n", f.Nam
e()) | |
| 79 g.Printf("return out.read%s;\n", seqRead(f.Type())) | |
| 80 g.Outdent() | |
| 81 g.Printf("}\n\n") | |
| 82 | |
| 83 g.Printf("public void set%s(%s v) {\n", f.Name(), g.javaType(f.T
ype())) | |
| 84 g.Indent() | |
| 85 g.Printf("Seq in = new Seq();\n") | |
| 86 g.Printf("Seq out = new Seq();\n") | |
| 87 g.Printf("in.writeRef(ref);\n") | |
| 88 g.Printf("in.write%s;\n", seqWrite(f.Type(), "v")) | |
| 89 g.Printf("Seq.send(DESCRIPTOR, FIELD_%s_SET, in, out);\n", f.Nam
e()) | |
| 90 g.Outdent() | |
| 91 g.Printf("}\n") | |
| 92 } | |
| 93 g.Printf("\n") | |
| 94 | |
| 95 for _, m := range methods { | |
| 96 g.genFunc(m, true) | |
| 97 } | |
| 98 | |
| 99 g.Printf("@Override public boolean equals(Object o) {\n") | |
| 100 g.Indent() | |
| 101 g.Printf("if (o == null || !(o instanceof %s)) {\n return false;\n}\n
", n) | |
| 102 g.Printf("%s that = (%s)o;\n", n, n) | |
| 103 for _, f := range fields { | |
| 104 nf := f.Name() | |
| 105 g.Printf("%s this%s = get%s();\n", g.javaType(f.Type()), nf, nf) | |
| 106 g.Printf("%s that%s = that.get%s();\n", g.javaType(f.Type()), nf
, nf) | |
| 107 if isJavaPrimitive(f.Type()) { | |
| 108 g.Printf("if (this%s != that%s) {\n return false;\n}\
n", nf, nf) | |
| 109 } else { | |
| 110 g.Printf("if (this%s == null) {\n", nf) | |
| 111 g.Indent() | |
| 112 g.Printf("if (that%s != null) {\n return false;\n}\n"
, nf) | |
| 113 g.Outdent() | |
| 114 g.Printf("} else if (!this%s.equals(that%s)) {\n retu
rn false;\n}\n", nf, nf) | |
| 115 } | |
| 116 } | |
| 117 g.Printf("return true;\n") | |
| 118 g.Outdent() | |
| 119 g.Printf("}\n\n") | |
| 120 | |
| 121 g.Printf("@Override public int hashCode() {\n") | |
| 122 g.Printf(" return java.util.Arrays.hashCode(new Object[] {") | |
| 123 for i, f := range fields { | |
| 124 if i > 0 { | |
| 125 g.Printf(", ") | |
| 126 } | |
| 127 g.Printf("get%s()", f.Name()) | |
| 128 } | |
| 129 g.Printf("});\n") | |
| 130 g.Printf("}\n\n") | |
| 131 | |
| 132 // TODO(crawshaw): use String() string if it is defined. | |
| 133 g.Printf("@Override public String toString() {\n") | |
| 134 g.Indent() | |
| 135 g.Printf("StringBuilder b = new StringBuilder();\n") | |
| 136 g.Printf(`b.append("%s").append("{");`, obj.Name()) | |
| 137 g.Printf("\n") | |
| 138 for _, f := range fields { | |
| 139 n := f.Name() | |
| 140 g.Printf(`b.append("%s:").append(get%s()).append(",");`, n, n) | |
| 141 g.Printf("\n") | |
| 142 } | |
| 143 g.Printf(`return b.append("}").toString();`) | |
| 144 g.Printf("\n") | |
| 145 g.Outdent() | |
| 146 g.Printf("}\n\n") | |
| 147 | |
| 148 g.Outdent() | |
| 149 g.Printf("}\n\n") | |
| 150 } | |
| 151 | |
| 152 func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) { | |
| 153 g.Printf("public static abstract class Stub implements %s {\n", o.Name()
) | |
| 154 g.Indent() | |
| 155 | |
| 156 g.Printf("static final String DESCRIPTOR = \"go.%s.%s\";\n\n", g.pkg.Nam
e(), o.Name()) | |
| 157 g.Printf("private final go.Seq.Ref ref;\n") | |
| 158 g.Printf("public Stub() {\n ref = go.Seq.createRef(this);\n}\n\n") | |
| 159 g.Printf("public go.Seq.Ref ref() { return ref; }\n\n") | |
| 160 | |
| 161 g.Printf("public void call(int code, go.Seq in, go.Seq out) {\n") | |
| 162 g.Indent() | |
| 163 g.Printf("switch (code) {\n") | |
| 164 | |
| 165 for i := 0; i < m.NumMethods(); i++ { | |
| 166 f := m.Method(i) | |
| 167 g.Printf("case Proxy.CALL_%s: {\n", f.Name()) | |
| 168 g.Indent() | |
| 169 | |
| 170 sig := f.Type().(*types.Signature) | |
| 171 for i := 0; i < sig.Params().Len(); i++ { | |
| 172 p := sig.Params().At(i) | |
| 173 jt := g.javaType(p.Type()) | |
| 174 g.Printf("%s param_%s = in.read%s;\n", jt, p.Name(), seq
Read(p.Type())) | |
| 175 } | |
| 176 | |
| 177 res := sig.Results() | |
| 178 var returnsError bool | |
| 179 var numRes = res.Len() | |
| 180 if (res.Len() == 1 && isErrorType(res.At(0).Type())) || | |
| 181 (res.Len() == 2 && isErrorType(res.At(1).Type())) { | |
| 182 numRes -= 1 | |
| 183 returnsError = true | |
| 184 } | |
| 185 | |
| 186 if returnsError { | |
| 187 g.Printf("try {\n") | |
| 188 g.Indent() | |
| 189 } | |
| 190 | |
| 191 if numRes > 0 { | |
| 192 g.Printf("%s result = ", g.javaType(res.At(0).Type())) | |
| 193 } | |
| 194 | |
| 195 g.Printf("this.%s(", f.Name()) | |
| 196 for i := 0; i < sig.Params().Len(); i++ { | |
| 197 if i > 0 { | |
| 198 g.Printf(", ") | |
| 199 } | |
| 200 g.Printf("param_%s", sig.Params().At(i).Name()) | |
| 201 } | |
| 202 g.Printf(");\n") | |
| 203 | |
| 204 if numRes > 0 { | |
| 205 g.Printf("out.write%s;\n", seqWrite(res.At(0).Type(), "r
esult")) | |
| 206 } | |
| 207 if returnsError { | |
| 208 g.Printf("out.writeUTF16(null);\n") | |
| 209 g.Outdent() | |
| 210 g.Printf("} catch (Exception e) {\n") | |
| 211 g.Indent() | |
| 212 if numRes > 0 { | |
| 213 resTyp := res.At(0).Type() | |
| 214 g.Printf("%s result = %s;\n", g.javaType(resTyp)
, g.javaTypeDefault(resTyp)) | |
| 215 g.Printf("out.write%s;\n", seqWrite(resTyp, "res
ult")) | |
| 216 } | |
| 217 g.Printf("out.writeUTF16(e.getMessage());\n") | |
| 218 g.Outdent() | |
| 219 g.Printf("}\n") | |
| 220 } | |
| 221 g.Printf("return;\n") | |
| 222 g.Outdent() | |
| 223 g.Printf("}\n") | |
| 224 } | |
| 225 | |
| 226 g.Printf("default:\n throw new RuntimeException(\"unknown code: \"+ c
ode);\n") | |
| 227 g.Printf("}\n") | |
| 228 g.Outdent() | |
| 229 g.Printf("}\n") | |
| 230 | |
| 231 g.Outdent() | |
| 232 g.Printf("}\n\n") | |
| 233 } | |
| 234 | |
| 235 const javaProxyPreamble = `static final class Proxy implements %s { | |
| 236 static final String DESCRIPTOR = Stub.DESCRIPTOR; | |
| 237 | |
| 238 private go.Seq.Ref ref; | |
| 239 | |
| 240 Proxy(go.Seq.Ref ref) { this.ref = ref; } | |
| 241 | |
| 242 public go.Seq.Ref ref() { return ref; } | |
| 243 | |
| 244 public void call(int code, go.Seq in, go.Seq out) { | |
| 245 throw new RuntimeException("cycle: cannot call proxy"); | |
| 246 } | |
| 247 | |
| 248 ` | |
| 249 | |
| 250 func (g *javaGen) genInterface(o *types.TypeName) { | |
| 251 iface := o.Type().(*types.Named).Underlying().(*types.Interface) | |
| 252 | |
| 253 g.Printf("public interface %s extends go.Seq.Object {\n", o.Name()) | |
| 254 g.Indent() | |
| 255 | |
| 256 methodSigErr := false | |
| 257 for i := 0; i < iface.NumMethods(); i++ { | |
| 258 if err := g.funcSignature(iface.Method(i), false); err != nil { | |
| 259 methodSigErr = true | |
| 260 g.errorf("%v", err) | |
| 261 } | |
| 262 g.Printf(";\n\n") | |
| 263 } | |
| 264 if methodSigErr { | |
| 265 return // skip stub generation, more of the same errors | |
| 266 } | |
| 267 | |
| 268 g.genInterfaceStub(o, iface) | |
| 269 | |
| 270 g.Printf(javaProxyPreamble, o.Name()) | |
| 271 g.Indent() | |
| 272 | |
| 273 for i := 0; i < iface.NumMethods(); i++ { | |
| 274 g.genFunc(iface.Method(i), true) | |
| 275 } | |
| 276 for i := 0; i < iface.NumMethods(); i++ { | |
| 277 g.Printf("static final int CALL_%s = 0x%x0a;\n", iface.Method(i)
.Name(), i+1) | |
| 278 } | |
| 279 | |
| 280 g.Outdent() | |
| 281 g.Printf("}\n") | |
| 282 | |
| 283 g.Outdent() | |
| 284 g.Printf("}\n\n") | |
| 285 } | |
| 286 | |
| 287 func isErrorType(T types.Type) bool { | |
| 288 return T == types.Universe.Lookup("error").Type() | |
| 289 } | |
| 290 | |
| 291 func isJavaPrimitive(T types.Type) bool { | |
| 292 b, ok := T.(*types.Basic) | |
| 293 if !ok { | |
| 294 return false | |
| 295 } | |
| 296 switch b.Kind() { | |
| 297 case types.Bool, types.Uint8, types.Float32, types.Float64, | |
| 298 types.Int, types.Int8, types.Int16, types.Int32, types.Int64: | |
| 299 return true | |
| 300 } | |
| 301 return false | |
| 302 } | |
| 303 | |
| 304 // javaType returns a string that can be used as a Java type. | |
| 305 func (g *javaGen) javaType(T types.Type) string { | |
| 306 switch T := T.(type) { | |
| 307 case *types.Basic: | |
| 308 switch T.Kind() { | |
| 309 case types.Bool: | |
| 310 return "boolean" | |
| 311 case types.Int: | |
| 312 return "long" | |
| 313 case types.Int8: | |
| 314 return "byte" | |
| 315 case types.Int16: | |
| 316 return "short" | |
| 317 case types.Int32: | |
| 318 return "int" | |
| 319 case types.Int64: | |
| 320 return "long" | |
| 321 case types.Uint8: | |
| 322 // TODO(crawshaw): Java bytes are signed, so this is | |
| 323 // questionable, but vital. | |
| 324 return "byte" | |
| 325 // TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32,
types.Uint64: | |
| 326 case types.Float32: | |
| 327 return "float" | |
| 328 case types.Float64: | |
| 329 return "double" | |
| 330 case types.String: | |
| 331 return "String" | |
| 332 default: | |
| 333 g.errorf("unsupported return type: %s", T) | |
| 334 return "TODO" | |
| 335 } | |
| 336 case *types.Slice: | |
| 337 elem := g.javaType(T.Elem()) | |
| 338 return elem + "[]" | |
| 339 | |
| 340 case *types.Pointer: | |
| 341 if _, ok := T.Elem().(*types.Named); ok { | |
| 342 return g.javaType(T.Elem()) | |
| 343 } | |
| 344 panic(fmt.Sprintf("unsupporter pointer to type: %s", T)) | |
| 345 case *types.Named: | |
| 346 n := T.Obj() | |
| 347 if n.Pkg() != g.pkg { | |
| 348 panic(fmt.Sprintf("type %s is in package %s, must be def
ined in package %s", n.Name(), n.Pkg().Name(), g.pkg.Name())) | |
| 349 } | |
| 350 // TODO(crawshaw): more checking here | |
| 351 return n.Name() | |
| 352 default: | |
| 353 g.errorf("unsupported javaType: %#+v, %s\n", T, T) | |
| 354 return "TODO" | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 // javaTypeDefault returns a string that represents the default value of the map
ped java type. | |
| 359 // TODO(hyangah): Combine javaType and javaTypeDefault? | |
| 360 func (g *javaGen) javaTypeDefault(T types.Type) string { | |
| 361 switch T := T.(type) { | |
| 362 case *types.Basic: | |
| 363 switch T.Kind() { | |
| 364 case types.Bool: | |
| 365 return "false" | |
| 366 case types.Int, types.Int8, types.Int16, types.Int32, | |
| 367 types.Int64, types.Uint8, types.Float32, types.Float64: | |
| 368 return "0" | |
| 369 case types.String: | |
| 370 return "null" | |
| 371 default: | |
| 372 g.errorf("unsupported return type: %s", T) | |
| 373 return "TODO" | |
| 374 } | |
| 375 case *types.Slice, *types.Pointer, *types.Named: | |
| 376 return "null" | |
| 377 | |
| 378 default: | |
| 379 g.errorf("unsupported javaType: %#+v, %s\n", T, T) | |
| 380 return "TODO" | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 var paramRE = regexp.MustCompile(`^p[0-9]+$`) | |
| 385 | |
| 386 // paramName replaces incompatible name with a p0-pN name. | |
| 387 // Missing names, or existing names of the form p[0-9] are incompatible. | |
| 388 // TODO(crawshaw): Replace invalid unicode names. | |
| 389 func paramName(params *types.Tuple, pos int) string { | |
| 390 name := params.At(pos).Name() | |
| 391 if name == "" || paramRE.MatchString(name) { | |
| 392 name = fmt.Sprintf("p%d", pos) | |
| 393 } | |
| 394 return name | |
| 395 } | |
| 396 | |
| 397 func (g *javaGen) funcSignature(o *types.Func, static bool) error { | |
| 398 sig := o.Type().(*types.Signature) | |
| 399 res := sig.Results() | |
| 400 | |
| 401 var returnsError bool | |
| 402 var ret string | |
| 403 switch res.Len() { | |
| 404 case 2: | |
| 405 if !isErrorType(res.At(1).Type()) { | |
| 406 return fmt.Errorf("second result value must be of type e
rror: %s", o) | |
| 407 } | |
| 408 returnsError = true | |
| 409 ret = g.javaType(res.At(0).Type()) | |
| 410 case 1: | |
| 411 if isErrorType(res.At(0).Type()) { | |
| 412 returnsError = true | |
| 413 ret = "void" | |
| 414 } else { | |
| 415 ret = g.javaType(res.At(0).Type()) | |
| 416 } | |
| 417 case 0: | |
| 418 ret = "void" | |
| 419 default: | |
| 420 return fmt.Errorf("too many result values: %s", o) | |
| 421 } | |
| 422 | |
| 423 g.Printf("public ") | |
| 424 if static { | |
| 425 g.Printf("static ") | |
| 426 } | |
| 427 g.Printf("%s %s(", ret, o.Name()) | |
| 428 params := sig.Params() | |
| 429 for i := 0; i < params.Len(); i++ { | |
| 430 if i > 0 { | |
| 431 g.Printf(", ") | |
| 432 } | |
| 433 v := sig.Params().At(i) | |
| 434 name := paramName(params, i) | |
| 435 jt := g.javaType(v.Type()) | |
| 436 g.Printf("%s %s", jt, name) | |
| 437 } | |
| 438 g.Printf(")") | |
| 439 if returnsError { | |
| 440 g.Printf(" throws Exception") | |
| 441 } | |
| 442 return nil | |
| 443 } | |
| 444 | |
| 445 func (g *javaGen) genFunc(o *types.Func, method bool) { | |
| 446 if err := g.funcSignature(o, !method); err != nil { | |
| 447 g.errorf("%v", err) | |
| 448 return | |
| 449 } | |
| 450 sig := o.Type().(*types.Signature) | |
| 451 res := sig.Results() | |
| 452 | |
| 453 g.Printf(" {\n") | |
| 454 g.Indent() | |
| 455 g.Printf("go.Seq _in = new go.Seq();\n") | |
| 456 g.Printf("go.Seq _out = new go.Seq();\n") | |
| 457 | |
| 458 returnsError := false | |
| 459 var resultType types.Type | |
| 460 if res.Len() > 0 { | |
| 461 if !isErrorType(res.At(0).Type()) { | |
| 462 resultType = res.At(0).Type() | |
| 463 } | |
| 464 if res.Len() > 1 || isErrorType(res.At(0).Type()) { | |
| 465 returnsError = true | |
| 466 } | |
| 467 } | |
| 468 if resultType != nil { | |
| 469 t := g.javaType(resultType) | |
| 470 g.Printf("%s _result;\n", t) | |
| 471 } | |
| 472 | |
| 473 if method { | |
| 474 g.Printf("_in.writeRef(ref);\n") | |
| 475 } | |
| 476 params := sig.Params() | |
| 477 for i := 0; i < params.Len(); i++ { | |
| 478 p := params.At(i) | |
| 479 g.Printf("_in.write%s;\n", seqWrite(p.Type(), p.Name())) | |
| 480 } | |
| 481 g.Printf("Seq.send(DESCRIPTOR, CALL_%s, _in, _out);\n", o.Name()) | |
| 482 if resultType != nil { | |
| 483 g.genRead("_result", "_out", resultType) | |
| 484 } | |
| 485 if returnsError { | |
| 486 g.Printf(`String _err = _out.readUTF16(); | |
| 487 if (_err != null) { | |
| 488 throw new Exception(_err); | |
| 489 } | |
| 490 `) | |
| 491 } | |
| 492 if resultType != nil { | |
| 493 g.Printf("return _result;\n") | |
| 494 } | |
| 495 g.Outdent() | |
| 496 g.Printf("}\n\n") | |
| 497 } | |
| 498 | |
| 499 func (g *javaGen) genRead(resName, seqName string, T types.Type) { | |
| 500 switch T := T.(type) { | |
| 501 case *types.Pointer: | |
| 502 // TODO(crawshaw): test *int | |
| 503 // TODO(crawshaw): test **Generator | |
| 504 switch T := T.Elem().(type) { | |
| 505 case *types.Named: | |
| 506 o := T.Obj() | |
| 507 if o.Pkg() != g.pkg { | |
| 508 g.errorf("type %s not defined in package %s", T,
g.pkg) | |
| 509 return | |
| 510 } | |
| 511 g.Printf("%s = new %s(%s.readRef());\n", resName, o.Name
(), seqName) | |
| 512 default: | |
| 513 g.errorf("unsupported type %s", T) | |
| 514 } | |
| 515 case *types.Named: | |
| 516 switch T.Underlying().(type) { | |
| 517 case *types.Interface, *types.Pointer: | |
| 518 o := T.Obj() | |
| 519 if o.Pkg() != g.pkg { | |
| 520 g.errorf("type %s not defined in package %s", T,
g.pkg) | |
| 521 return | |
| 522 } | |
| 523 g.Printf("%s = new %s.Proxy(%s.readRef());\n", resName,
o.Name(), seqName) | |
| 524 default: | |
| 525 g.errorf("unsupported, direct named type %s", T) | |
| 526 } | |
| 527 default: | |
| 528 g.Printf("%s = %s.read%s();\n", resName, seqName, seqType(T)) | |
| 529 } | |
| 530 } | |
| 531 | |
| 532 func (g *javaGen) errorf(format string, args ...interface{}) { | |
| 533 g.err = append(g.err, fmt.Errorf(format, args...)) | |
| 534 } | |
| 535 | |
| 536 const javaPreamble = `// Java Package %s is a proxy for talking to a Go program. | |
| 537 // gobind -lang=java %s | |
| 538 // | |
| 539 // File is generated by gobind. Do not edit. | |
| 540 package go.%s; | |
| 541 | |
| 542 import go.Seq; | |
| 543 | |
| 544 ` | |
| 545 | |
| 546 func (g *javaGen) gen() error { | |
| 547 g.Printf(javaPreamble, g.pkg.Name(), g.pkg.Path(), g.pkg.Name()) | |
| 548 | |
| 549 firstRune, size := utf8.DecodeRuneInString(g.pkg.Name()) | |
| 550 className := string(unicode.ToUpper(firstRune)) + g.pkg.Name()[size:] | |
| 551 | |
| 552 g.Printf("public abstract class %s {\n", className) | |
| 553 g.Indent() | |
| 554 g.Printf("private %s() {} // uninstantiable\n\n", className) | |
| 555 scope := g.pkg.Scope() | |
| 556 names := scope.Names() | |
| 557 var funcs []string | |
| 558 for _, name := range names { | |
| 559 obj := scope.Lookup(name) | |
| 560 if !obj.Exported() { | |
| 561 continue | |
| 562 } | |
| 563 | |
| 564 switch o := obj.(type) { | |
| 565 // TODO(crawshaw): case *types.Const: | |
| 566 // TODO(crawshaw): case *types.Var: | |
| 567 case *types.Func: | |
| 568 g.genFunc(o, false) | |
| 569 funcs = append(funcs, o.Name()) | |
| 570 case *types.TypeName: | |
| 571 named := o.Type().(*types.Named) | |
| 572 switch t := named.Underlying().(type) { | |
| 573 case *types.Struct: | |
| 574 g.genStruct(o, t) | |
| 575 case *types.Interface: | |
| 576 g.genInterface(o) | |
| 577 default: | |
| 578 g.errorf("%s: cannot generate binding for %s: %T
", g.fset.Position(o.Pos()), o.Name(), t) | |
| 579 continue | |
| 580 } | |
| 581 default: | |
| 582 g.errorf("unsupported exported type: ", obj) | |
| 583 } | |
| 584 } | |
| 585 | |
| 586 for i, name := range funcs { | |
| 587 g.Printf("private static final int CALL_%s = %d;\n", name, i+1) | |
| 588 } | |
| 589 | |
| 590 g.Printf("private static final String DESCRIPTOR = %q;\n", g.pkg.Name()) | |
| 591 g.Outdent() | |
| 592 g.Printf("}\n") | |
| 593 | |
| 594 if len(g.err) > 0 { | |
| 595 return g.err | |
| 596 } | |
| 597 return nil | |
| 598 } | |
| OLD | NEW |