Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: third_party/go/src/golang.org/x/mobile/bind/genjava.go

Issue 1275153002: Remove third_party/golang.org/x/mobile as it is no longer used with Go 1.5. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Remove golang.org/x/mobile Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « third_party/go/src/golang.org/x/mobile/bind/gengo.go ('k') | third_party/go/src/golang.org/x/mobile/bind/java/Seq.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698