From 63412932cad33598a2ad1995b01c6e7c83121aa0 Mon Sep 17 00:00:00 2001 From: Uriel Corfa Date: Fri, 14 Jul 2017 21:08:14 +0800 Subject: [PATCH] Add an RPC server for annotations. --- cmd/serve/proto/protoc.sh | 18 ++ cmd/serve/proto/serve.pb.go | 392 +++++++++++++++++++++++++++++ cmd/serve/proto/serve.pb.gw.go | 187 ++++++++++++++ cmd/serve/proto/serve.proto | 61 +++++ cmd/serve/proto/serve.swagger.json | 147 +++++++++++ cmd/serve/serve.go | 104 ++++++++ corpus.go | 20 ++ 7 files changed, 929 insertions(+) create mode 100755 cmd/serve/proto/protoc.sh create mode 100644 cmd/serve/proto/serve.pb.go create mode 100644 cmd/serve/proto/serve.pb.gw.go create mode 100644 cmd/serve/proto/serve.proto create mode 100644 cmd/serve/proto/serve.swagger.json create mode 100644 cmd/serve/serve.go diff --git a/cmd/serve/proto/protoc.sh b/cmd/serve/proto/protoc.sh new file mode 100755 index 0000000..5789440 --- /dev/null +++ b/cmd/serve/proto/protoc.sh @@ -0,0 +1,18 @@ +#!/bin/sh +protoc -I/usr/local/include -I. \ + -I$GOPATH/src \ + -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ + --go_out=plugins=grpc:. \ + serve.proto + +protoc -I/usr/local/include -I. \ + -I$GOPATH/src \ + -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ + --grpc-gateway_out=logtostderr=true:. \ + serve.proto + +protoc -I/usr/local/include -I. \ + -I$GOPATH/src \ + -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ + --swagger_out=logtostderr=true:. \ + serve.proto diff --git a/cmd/serve/proto/serve.pb.go b/cmd/serve/proto/serve.pb.go new file mode 100644 index 0000000..5c36ac6 --- /dev/null +++ b/cmd/serve/proto/serve.pb.go @@ -0,0 +1,392 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: serve.proto + +/* +Package serve is a generated protocol buffer package. + +It is generated from these files: + serve.proto + +It has these top-level messages: + GetFileRequest + GetFileResponse + GetAnnotationsRequest + GetAnnotationsResponse + Annotation + Location +*/ +package serve + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Type int32 + +const ( + Type_Instantiation Type = 0 + Type_Call Type = 1 + Type_Implementation Type = 2 + Type_Extension Type = 3 + Type_Import Type = 4 + Type_Reference Type = 5 +) + +var Type_name = map[int32]string{ + 0: "Instantiation", + 1: "Call", + 2: "Implementation", + 3: "Extension", + 4: "Import", + 5: "Reference", +} +var Type_value = map[string]int32{ + "Instantiation": 0, + "Call": 1, + "Implementation": 2, + "Extension": 3, + "Import": 4, + "Reference": 5, +} + +func (x Type) String() string { + return proto.EnumName(Type_name, int32(x)) +} +func (Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type GetFileRequest struct { + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` +} + +func (m *GetFileRequest) Reset() { *m = GetFileRequest{} } +func (m *GetFileRequest) String() string { return proto.CompactTextString(m) } +func (*GetFileRequest) ProtoMessage() {} +func (*GetFileRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *GetFileRequest) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +type GetFileResponse struct { + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` + Contents string `protobuf:"bytes,2,opt,name=contents" json:"contents,omitempty"` +} + +func (m *GetFileResponse) Reset() { *m = GetFileResponse{} } +func (m *GetFileResponse) String() string { return proto.CompactTextString(m) } +func (*GetFileResponse) ProtoMessage() {} +func (*GetFileResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *GetFileResponse) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *GetFileResponse) GetContents() string { + if m != nil { + return m.Contents + } + return "" +} + +type GetAnnotationsRequest struct { + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` +} + +func (m *GetAnnotationsRequest) Reset() { *m = GetAnnotationsRequest{} } +func (m *GetAnnotationsRequest) String() string { return proto.CompactTextString(m) } +func (*GetAnnotationsRequest) ProtoMessage() {} +func (*GetAnnotationsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *GetAnnotationsRequest) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +type GetAnnotationsResponse struct { + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` + Annotation []*Annotation `protobuf:"bytes,2,rep,name=annotation" json:"annotation,omitempty"` +} + +func (m *GetAnnotationsResponse) Reset() { *m = GetAnnotationsResponse{} } +func (m *GetAnnotationsResponse) String() string { return proto.CompactTextString(m) } +func (*GetAnnotationsResponse) ProtoMessage() {} +func (*GetAnnotationsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GetAnnotationsResponse) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *GetAnnotationsResponse) GetAnnotation() []*Annotation { + if m != nil { + return m.Annotation + } + return nil +} + +type Annotation struct { + From *Location `protobuf:"bytes,1,opt,name=from" json:"from,omitempty"` + To *Location `protobuf:"bytes,2,opt,name=to" json:"to,omitempty"` + Type Type `protobuf:"varint,3,opt,name=type,enum=serve.Type" json:"type,omitempty"` +} + +func (m *Annotation) Reset() { *m = Annotation{} } +func (m *Annotation) String() string { return proto.CompactTextString(m) } +func (*Annotation) ProtoMessage() {} +func (*Annotation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *Annotation) GetFrom() *Location { + if m != nil { + return m.From + } + return nil +} + +func (m *Annotation) GetTo() *Location { + if m != nil { + return m.To + } + return nil +} + +func (m *Annotation) GetType() Type { + if m != nil { + return m.Type + } + return Type_Instantiation +} + +type Location struct { + Package string `protobuf:"bytes,1,opt,name=package" json:"package,omitempty"` + Filename string `protobuf:"bytes,2,opt,name=filename" json:"filename,omitempty"` + StartLine int64 `protobuf:"varint,3,opt,name=start_line,json=startLine" json:"start_line,omitempty"` + StartColumn int64 `protobuf:"varint,4,opt,name=start_column,json=startColumn" json:"start_column,omitempty"` + EndLine int64 `protobuf:"varint,5,opt,name=end_line,json=endLine" json:"end_line,omitempty"` + EndColumn int64 `protobuf:"varint,6,opt,name=end_column,json=endColumn" json:"end_column,omitempty"` +} + +func (m *Location) Reset() { *m = Location{} } +func (m *Location) String() string { return proto.CompactTextString(m) } +func (*Location) ProtoMessage() {} +func (*Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *Location) GetPackage() string { + if m != nil { + return m.Package + } + return "" +} + +func (m *Location) GetFilename() string { + if m != nil { + return m.Filename + } + return "" +} + +func (m *Location) GetStartLine() int64 { + if m != nil { + return m.StartLine + } + return 0 +} + +func (m *Location) GetStartColumn() int64 { + if m != nil { + return m.StartColumn + } + return 0 +} + +func (m *Location) GetEndLine() int64 { + if m != nil { + return m.EndLine + } + return 0 +} + +func (m *Location) GetEndColumn() int64 { + if m != nil { + return m.EndColumn + } + return 0 +} + +func init() { + proto.RegisterType((*GetFileRequest)(nil), "serve.GetFileRequest") + proto.RegisterType((*GetFileResponse)(nil), "serve.GetFileResponse") + proto.RegisterType((*GetAnnotationsRequest)(nil), "serve.GetAnnotationsRequest") + proto.RegisterType((*GetAnnotationsResponse)(nil), "serve.GetAnnotationsResponse") + proto.RegisterType((*Annotation)(nil), "serve.Annotation") + proto.RegisterType((*Location)(nil), "serve.Location") + proto.RegisterEnum("serve.Type", Type_name, Type_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Goref service + +type GorefClient interface { + GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error) + GetAnnotations(ctx context.Context, in *GetAnnotationsRequest, opts ...grpc.CallOption) (*GetAnnotationsResponse, error) +} + +type gorefClient struct { + cc *grpc.ClientConn +} + +func NewGorefClient(cc *grpc.ClientConn) GorefClient { + return &gorefClient{cc} +} + +func (c *gorefClient) GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error) { + out := new(GetFileResponse) + err := grpc.Invoke(ctx, "/serve.Goref/GetFile", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gorefClient) GetAnnotations(ctx context.Context, in *GetAnnotationsRequest, opts ...grpc.CallOption) (*GetAnnotationsResponse, error) { + out := new(GetAnnotationsResponse) + err := grpc.Invoke(ctx, "/serve.Goref/GetAnnotations", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Goref service + +type GorefServer interface { + GetFile(context.Context, *GetFileRequest) (*GetFileResponse, error) + GetAnnotations(context.Context, *GetAnnotationsRequest) (*GetAnnotationsResponse, error) +} + +func RegisterGorefServer(s *grpc.Server, srv GorefServer) { + s.RegisterService(&_Goref_serviceDesc, srv) +} + +func _Goref_GetFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GorefServer).GetFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/serve.Goref/GetFile", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GorefServer).GetFile(ctx, req.(*GetFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Goref_GetAnnotations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAnnotationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GorefServer).GetAnnotations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/serve.Goref/GetAnnotations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GorefServer).GetAnnotations(ctx, req.(*GetAnnotationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Goref_serviceDesc = grpc.ServiceDesc{ + ServiceName: "serve.Goref", + HandlerType: (*GorefServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFile", + Handler: _Goref_GetFile_Handler, + }, + { + MethodName: "GetAnnotations", + Handler: _Goref_GetAnnotations_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "serve.proto", +} + +func init() { proto.RegisterFile("serve.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 495 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x53, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0xc5, 0x8e, 0xf3, 0x35, 0xa6, 0xa9, 0x3b, 0x52, 0x2b, 0x63, 0x35, 0x4a, 0x6a, 0x90, 0x88, + 0x82, 0x54, 0xab, 0xe1, 0xcc, 0xa1, 0xaa, 0x20, 0x8a, 0xd4, 0x93, 0xc5, 0x89, 0x4b, 0xb5, 0x38, + 0x93, 0x60, 0x61, 0xef, 0x1a, 0xef, 0x36, 0xa2, 0x42, 0x5c, 0xf8, 0x0b, 0xfc, 0x1d, 0xfe, 0x05, + 0x47, 0xae, 0xfc, 0x10, 0xe4, 0x5d, 0xa7, 0x0e, 0xa5, 0xf4, 0xe6, 0x99, 0xf7, 0xde, 0x3c, 0xcf, + 0xe8, 0x2d, 0xb8, 0x92, 0xca, 0x0d, 0x9d, 0x16, 0xa5, 0x50, 0x02, 0xdb, 0xba, 0x08, 0x8e, 0xd7, + 0x42, 0xac, 0x33, 0x8a, 0x58, 0x91, 0x46, 0x8c, 0x73, 0xa1, 0x98, 0x4a, 0x05, 0x97, 0x86, 0x14, + 0x3e, 0x83, 0xc1, 0x9c, 0xd4, 0x9b, 0x34, 0xa3, 0x98, 0x3e, 0x5d, 0x93, 0x54, 0x88, 0xe0, 0x14, + 0x4c, 0x7d, 0xf0, 0xad, 0xb1, 0x35, 0xe9, 0xc7, 0xfa, 0x3b, 0x3c, 0x87, 0xfd, 0x5b, 0x96, 0x2c, + 0x04, 0x97, 0x74, 0x1f, 0x0d, 0x03, 0xe8, 0x25, 0x82, 0x2b, 0xe2, 0x4a, 0xfa, 0xb6, 0xee, 0xdf, + 0xd6, 0xe1, 0x0b, 0x38, 0x9c, 0x93, 0x3a, 0x6f, 0x7e, 0xe0, 0x21, 0xbf, 0x2b, 0x38, 0xba, 0x4b, + 0x7e, 0xc0, 0xf6, 0x0c, 0xa0, 0x59, 0xcc, 0xb7, 0xc7, 0xad, 0x89, 0x3b, 0x3b, 0x38, 0x35, 0xa7, + 0x68, 0x66, 0xc4, 0x3b, 0xa4, 0x50, 0x02, 0x34, 0x08, 0x3e, 0x05, 0x67, 0x55, 0x8a, 0x5c, 0x0f, + 0x75, 0x67, 0xfb, 0xb5, 0xf4, 0x52, 0x24, 0x46, 0xa8, 0x41, 0x1c, 0x81, 0xad, 0x84, 0x5e, 0xeb, + 0x1e, 0x8a, 0xad, 0x04, 0x8e, 0xc0, 0x51, 0x37, 0x05, 0xf9, 0xad, 0xb1, 0x35, 0x19, 0xcc, 0xdc, + 0x9a, 0xf2, 0xf6, 0xa6, 0xa0, 0x58, 0x03, 0xe1, 0x0f, 0x0b, 0x7a, 0x5b, 0x05, 0xfa, 0xd0, 0x2d, + 0x58, 0xf2, 0x91, 0xad, 0xa9, 0xde, 0x65, 0x5b, 0x56, 0x57, 0x5c, 0xa5, 0x19, 0x71, 0x96, 0xd3, + 0xf6, 0x8a, 0xdb, 0x1a, 0x87, 0x00, 0x52, 0xb1, 0x52, 0x5d, 0x65, 0x29, 0x37, 0x4e, 0xad, 0xb8, + 0xaf, 0x3b, 0x97, 0x29, 0x27, 0x3c, 0x81, 0xc7, 0x06, 0x4e, 0x44, 0x76, 0x9d, 0x73, 0xdf, 0xd1, + 0x04, 0x57, 0xf7, 0x2e, 0x74, 0x0b, 0x9f, 0x40, 0x8f, 0xf8, 0xd2, 0xe8, 0xdb, 0x1a, 0xee, 0x12, + 0x5f, 0x6a, 0xf5, 0x10, 0xa0, 0x82, 0x6a, 0x6d, 0xc7, 0x0c, 0x27, 0xbe, 0x34, 0xca, 0x29, 0x03, + 0xa7, 0x5a, 0x06, 0x0f, 0x60, 0x6f, 0xc1, 0xa5, 0x62, 0x5c, 0xa5, 0x7a, 0x15, 0xef, 0x11, 0xf6, + 0xc0, 0xb9, 0x60, 0x59, 0xe6, 0x59, 0x88, 0x30, 0x58, 0xe4, 0x45, 0x46, 0x39, 0x71, 0x73, 0x5c, + 0xcf, 0xc6, 0x3d, 0xe8, 0xbf, 0xfe, 0xac, 0x88, 0xcb, 0xaa, 0x6c, 0x21, 0x40, 0x67, 0x91, 0x17, + 0xa2, 0x54, 0x9e, 0x53, 0x41, 0x31, 0xad, 0xa8, 0x24, 0x9e, 0x90, 0xd7, 0x9e, 0xfd, 0xb2, 0xa0, + 0x3d, 0x17, 0x25, 0xad, 0xf0, 0x1d, 0x74, 0xeb, 0xc4, 0xe1, 0x61, 0x7d, 0xc9, 0xbf, 0x73, 0x1a, + 0x1c, 0xdd, 0x6d, 0x9b, 0x84, 0x84, 0xe3, 0x6f, 0x3f, 0x7f, 0x7f, 0xb7, 0x03, 0xf4, 0xa3, 0xcd, + 0x59, 0xb4, 0xae, 0x86, 0x45, 0xd5, 0xf9, 0xa2, 0x2f, 0x55, 0x56, 0x5e, 0x4d, 0xa7, 0x5f, 0x71, + 0xa3, 0x33, 0xbf, 0x93, 0x2e, 0x3c, 0x6e, 0x66, 0xfd, 0x9b, 0xd0, 0x60, 0xf8, 0x1f, 0xb4, 0x36, + 0x7c, 0xae, 0x0d, 0x4f, 0x70, 0xd4, 0x18, 0xee, 0xbc, 0xb3, 0xc6, 0xf7, 0x7d, 0x47, 0x3f, 0xb9, + 0x97, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x19, 0x3e, 0x37, 0xa6, 0x03, 0x00, 0x00, +} diff --git a/cmd/serve/proto/serve.pb.gw.go b/cmd/serve/proto/serve.pb.gw.go new file mode 100644 index 0000000..53a84ca --- /dev/null +++ b/cmd/serve/proto/serve.pb.gw.go @@ -0,0 +1,187 @@ +// Code generated by protoc-gen-grpc-gateway +// source: serve.proto +// DO NOT EDIT! + +/* +Package serve is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package serve + +import ( + "io" + "net/http" + + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray + +func request_Goref_GetFile_0(ctx context.Context, marshaler runtime.Marshaler, client GorefClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetFileRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["path"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "path") + } + + protoReq.Path, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "path", err) + } + + msg, err := client.GetFile(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func request_Goref_GetAnnotations_0(ctx context.Context, marshaler runtime.Marshaler, client GorefClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetAnnotationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["path"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "path") + } + + protoReq.Path, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "path", err) + } + + msg, err := client.GetAnnotations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +// RegisterGorefHandlerFromEndpoint is same as RegisterGorefHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterGorefHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterGorefHandler(ctx, mux, conn) +} + +// RegisterGorefHandler registers the http handlers for service Goref to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterGorefHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + client := NewGorefClient(conn) + + mux.Handle("GET", pattern_Goref_GetFile_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Goref_GetFile_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Goref_GetFile_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Goref_GetAnnotations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Goref_GetAnnotations_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Goref_GetAnnotations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Goref_GetFile_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 3, 0, 4, 1, 5, 3}, []string{"v1", "goref", "file", "path"}, "")) + + pattern_Goref_GetAnnotations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 3, 0, 4, 1, 5, 3}, []string{"v1", "goref", "annotations", "path"}, "")) +) + +var ( + forward_Goref_GetFile_0 = runtime.ForwardResponseMessage + + forward_Goref_GetAnnotations_0 = runtime.ForwardResponseMessage +) diff --git a/cmd/serve/proto/serve.proto b/cmd/serve/proto/serve.proto new file mode 100644 index 0000000..c2c227c --- /dev/null +++ b/cmd/serve/proto/serve.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; + +import "google/api/annotations.proto"; + +package serve; + +message GetFileRequest { + string path = 1; +} + +message GetFileResponse { + string path = 1; + string contents = 2; +} + +message GetAnnotationsRequest { + string path = 1; +} + +message GetAnnotationsResponse { + string path = 1; + repeated Annotation annotation = 2; +} + +message Annotation { + Location from = 1; + Location to = 2; + Type type = 3; +} + +message Location { + string package = 1; + string filename = 2; + int64 start_line = 3; + int64 start_column = 4; + int64 end_line = 5; + int64 end_column = 6; +} + +enum Type { + Instantiation = 0; + Call = 1; + Implementation = 2; + Extension = 3; + Import = 4; + Reference = 5; +} + +service Goref { + rpc GetFile(GetFileRequest) returns (GetFileResponse) { + option (google.api.http) = { + get: "/v1/goref/file/{path=**}" + }; + } + + rpc GetAnnotations(GetAnnotationsRequest) returns (GetAnnotationsResponse) { + option (google.api.http) = { + get: "/v1/goref/annotations/{path=**}" + }; + } +} diff --git a/cmd/serve/proto/serve.swagger.json b/cmd/serve/proto/serve.swagger.json new file mode 100644 index 0000000..50bd22d --- /dev/null +++ b/cmd/serve/proto/serve.swagger.json @@ -0,0 +1,147 @@ +{ + "swagger": "2.0", + "info": { + "title": "serve.proto", + "version": "version not set" + }, + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/v1/goref/annotations/{path}": { + "get": { + "operationId": "GetAnnotations", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/serveGetAnnotationsResponse" + } + } + }, + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "Goref" + ] + } + }, + "/v1/goref/file/{path}": { + "get": { + "operationId": "GetFile", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/serveGetFileResponse" + } + } + }, + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "Goref" + ] + } + } + }, + "definitions": { + "serveAnnotation": { + "type": "object", + "properties": { + "from": { + "$ref": "#/definitions/serveLocation" + }, + "to": { + "$ref": "#/definitions/serveLocation" + }, + "type": { + "$ref": "#/definitions/serveType" + } + } + }, + "serveGetAnnotationsResponse": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "annotation": { + "type": "array", + "items": { + "$ref": "#/definitions/serveAnnotation" + } + } + } + }, + "serveGetFileResponse": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "contents": { + "type": "string" + } + } + }, + "serveLocation": { + "type": "object", + "properties": { + "package": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "start_line": { + "type": "string", + "format": "int64" + }, + "start_column": { + "type": "string", + "format": "int64" + }, + "end_line": { + "type": "string", + "format": "int64" + }, + "end_column": { + "type": "string", + "format": "int64" + } + } + }, + "serveType": { + "type": "string", + "enum": [ + "Instantiation", + "Call", + "Implementation", + "Extension", + "Import", + "Reference" + ], + "default": "Instantiation" + } + } +} diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go new file mode 100644 index 0000000..67b5006 --- /dev/null +++ b/cmd/serve/serve.go @@ -0,0 +1,104 @@ +package main + +import ( + "fmt" + "golang.org/x/net/context" + "io/ioutil" + "log" + "net" + "net/http" + "path/filepath" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "google.golang.org/grpc" + "github.com/korfuri/goref" + pb "github.com/korfuri/goref/cmd/serve/proto" + "google.golang.org/grpc/reflection" +) + +const ( + gatewayListenAddr = ":6061" + grpcListenAddr = "127.0.0.1:6062" +) + + +// server implements pb.GorefServer +type server struct{ + corpora []goref.Corpus +} + +func (s server) GetAnnotations(ctx context.Context, req *pb.GetAnnotationsRequest) (*pb.GetAnnotationsResponse, error) { + return nil, nil +} +func (s server) GetFile(ctx context.Context, req *pb.GetFileRequest) (*pb.GetFileResponse, error) { + fmt.Printf("path: %s\n", req.Path) + fpath := req.Path + if filepath.Ext(fpath) != ".go" { + return nil, fmt.Errorf("Not found: invalid extension") + } + var corpus goref.Corpus + for _, c := range s.corpora { + if c.ContainsRel(fpath) { + corpus = c + break + } + } + if corpus == "" { + return nil, fmt.Errorf("Not found under any corpus") + } + if f, err := ioutil.ReadFile(corpus.Abs(fpath)); err == nil { + return &pb.GetFileResponse{ + Path: fpath, + Contents: string(f), + }, nil + } else { + return nil, fmt.Errorf("Internal server error") + } + + +} + +func runGRPC(grpcReady chan struct{}) error { + lis, err := net.Listen("tcp", grpcListenAddr) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + s := grpc.NewServer() + pb.RegisterGorefServer(s, &server{ + corpora: goref.DefaultCorpora(), + }) + // Register reflection service on gRPC server. + reflection.Register(s) + grpcReady <- struct{}{} + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } + return nil +} + +func runGateway(grpcReady <-chan struct{}) error { + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + <- grpcReady + + mux := runtime.NewServeMux() + opts := []grpc.DialOption{grpc.WithInsecure()} + err := pb.RegisterGorefHandlerFromEndpoint(ctx, mux, grpcListenAddr, opts) + if err != nil { + return err + } + + return http.ListenAndServe(gatewayListenAddr, mux) +} + +func Do() { + grpcReady := make(chan struct{}) + go runGateway(grpcReady) + runGRPC(grpcReady) +} + +func main() { + Do() +} diff --git a/corpus.go b/corpus.go index 5dfb830..7d80a92 100644 --- a/corpus.go +++ b/corpus.go @@ -3,6 +3,7 @@ package goref import ( "fmt" "go/build" + "os" "path/filepath" "strings" ) @@ -32,6 +33,25 @@ func (c Corpus) Contains(fpath string) bool { return !strings.HasPrefix(rel, "../") && rel != ".." } +// ContainsRel returns whether the provided relpath exists under this +// Corpus. +func (c Corpus) ContainsRel(rel string) bool { + fpath := c.Abs(rel) + fi, err := os.Stat(fpath) + if err != nil { + return false + } + return (fi.Mode() & os.ModeType) == 0 +} + +// Abs returns the absolute path of a file within a Corpus. +func (c Corpus) Abs(rel string) string { + if string(c) == "" { + return "" + } + return filepath.Join(string(c), rel) +} + // Rel returns the relative path of a file within a Corpus. // If the string does not belong to the corpus, it returns fpath. func (c Corpus) Rel(fpath string) string {