Giter VIP home page Giter VIP logo

protoc-plugin's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

protoc-plugin's Issues

Output includes dependencies

It has been observed that the latest plugin will inadvertently output code for dependencies even if those dependencies were not specifically slated for compilation. This needs to be cleaned up.

Crash during compilation

Steps to reproduce

Compile any .proto file

Expected result

Successful production of Clojure output for the .proto

Observed result

The plugin crashes (see below)

protoc --clojure_out=grpc-client,grpc-server:src --proto_path=resources resources/addressbook.proto
Exception in thread "main" java.lang.NullPointerException
	at clojure.lang.RT.intCast(RT.java:1220)
	at protojure.plugin.main$_main.invokeStatic(main.clj:86)
	at protojure.plugin.main$_main.doInvoke(main.clj:80)
	at clojure.lang.RestFn.invoke(RestFn.java:397)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at protojure.plugin.main.main(Unknown Source)
--clojure_out: protoc-gen-clojure: Plugin failed with status code 1.
make: *** [all] Error 1

Support multiple .proto files declaring a common 'package'

As it stands right now, the plugin generates output files based on the number of input .protos. This doesn't work when multiple .proto files declare the same 'package'. The end result is that the plugin proposes multiple outputs with the same filename (since the filename is based on the package) and protoc rejects the output.

This common packaging is perfectly normal, and is utilized in two high-profile projects: Protobufs itself (via the Google "Well Known Types" and the Hyperledger Fabric project.

Therefore, our plugin needs to support this use case.

Support for optional fields in proto3?

While attempting to protoc compile a bunch of .proto files, several times I encountered this message:

foo.proto is a proto3 file that contains optional fields, 
but code generator protoc-gen-clojure hasn't been updated to support optional fields in proto3. 
Please ask the owner of this code generator to support proto3 optional.

What is the prognosis/timeline for this, if any?
If not, any idea how much work it would be for someone who knows almost nothing about protobufs to add this?

Missing fields in generated records when a message field is named "values"

In 0.9.3 when a Protocol Buffer message contains a field named: "values", all of the fields (except the "values" field) are missing in the generated code.

The message:

message A {
  string field1 = 1;
  string values = 2;
  string field3 = 3;
}

Produces:

(defrecord A-record [values]
  pb/Writer
  (serialize [this os]
    (serdes.core/write-String 2  {:optimize true} (:values this) os))
  pb/TypeReflection
  (gettype [this]
    "com.example.ab.A"))

(s/def :com.example.ab.A/values string?)
(s/def ::A-spec (s/keys :opt-un [:com.example.ab.A/values ]))
(def A-defaults {:values "" })

A similar message containing a field named: "values2"

message B {
  string field1 = 1;
  string values2 = 2;
  string field3 = 3;
}

Produces the correct record

(defrecord B-record [field1 values2 field3]
  pb/Writer
  (serialize [this os]
    (serdes.core/write-String 1  {:optimize true} (:field1 this) os)
    (serdes.core/write-String 2  {:optimize true} (:values2 this) os)
    (serdes.core/write-String 3  {:optimize true} (:field3 this) os))
  pb/TypeReflection
  (gettype [this]
    "com.example.ab.B"))

(s/def :com.example.ab.B/field1 string?)
(s/def :com.example.ab.B/values2 string?)
(s/def :com.example.ab.B/field3 string?)
(s/def ::B-spec (s/keys :opt-un [:com.example.ab.B/field1 :com.example.ab.B/values2 :com.example.ab.B/field3 ]))
(def B-defaults {:field1 "" :values2 "" :field3 "" })

from edn to google.protobuf.struct

Hello, is there anyway to parse and edn like {#xtdb/id \"1073c72f6e04ee66347a627efd9096910b790e66\" {:map {:k2 \"v2\"}, :bool? true, :number 3.0, :listing [1.0 2.0 3.0 4.0], :key \"ARROZ\", :crux.db/id :id1}}to google.protobuf.struct ?

Generated code:

;-----------------------------------------------------------------------------
; SpeculativeTxResponse
;-----------------------------------------------------------------------------
(defrecord SpeculativeTxResponse-record [valid-time tx-time tx-id entity-cache-size batch-size edn-document]
  pb/Writer
  (serialize [this os]
    (serdes.core/write-String 1  {:optimize true} (:valid-time this) os)
    (serdes.core/write-String 2  {:optimize true} (:tx-time this) os)
    (serdes.core/write-Int64 3  {:optimize true} (:tx-id this) os)
    (serdes.core/write-Int32 4  {:optimize true} (:entity-cache-size this) os)
    (serdes.core/write-Int32 5  {:optimize true} (:batch-size this) os)
    (serdes.core/write-embedded 6 (:edn-document this) os))
  pb/TypeReflection
  (gettype [this]
    "com.xtdb.protos.SpeculativeTxResponse"))

(s/def :com.xtdb.protos.SpeculativeTxResponse/valid-time string?)
(s/def :com.xtdb.protos.SpeculativeTxResponse/tx-time string?)
(s/def :com.xtdb.protos.SpeculativeTxResponse/tx-id int?)
(s/def :com.xtdb.protos.SpeculativeTxResponse/entity-cache-size int?)
(s/def :com.xtdb.protos.SpeculativeTxResponse/batch-size int?)

(s/def ::SpeculativeTxResponse-spec (s/keys :opt-un [:com.xtdb.protos.SpeculativeTxResponse/valid-time :com.xtdb.protos.SpeculativeTxResponse/tx-time :com.xtdb.protos.SpeculativeTxResponse/tx-id :com.xtdb.protos.SpeculativeTxResponse/entity-cache-size :com.xtdb.protos.SpeculativeTxResponse/batch-size]))
(def SpeculativeTxResponse-defaults {:valid-time "" :tx-time "" :tx-id 0 :entity-cache-size 0 :batch-size 0})

(defn cis->SpeculativeTxResponse
  "CodedInputStream to SpeculativeTxResponse"
  [is]
  (map->SpeculativeTxResponse-record (tag-map SpeculativeTxResponse-defaults (fn [tag index] (case index 1 [:valid-time (serdes.core/cis->String is)] 2 [:tx-time (serdes.core/cis->String is)] 3 [:tx-id (serdes.core/cis->Int64 is)] 4 [:entity-cache-size (serdes.core/cis->Int32 is)] 5 [:batch-size (serdes.core/cis->Int32 is)] 6 [:edn-document (com.google.protobuf/ecis->Struct is)] [index (serdes.core/cis->undefined tag is)])) is)))

(defn ecis->SpeculativeTxResponse
  "Embedded CodedInputStream to SpeculativeTxResponse"
  [is]
  (serdes.core/cis->embedded cis->SpeculativeTxResponse is))

(defn new-SpeculativeTxResponse
  "Creates a new instance from a map, similar to map->SpeculativeTxResponse except that
  it properly accounts for nested messages, when applicable.
  "
  [init]
  {:pre [(if (s/valid? ::SpeculativeTxResponse-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::SpeculativeTxResponse-spec init))))]}
  (-> (merge SpeculativeTxResponse-defaults init)
      (cond-> (some? (get init :edn-document)) (update :edn-document com.google.protobuf/new-Struct))
      (map->SpeculativeTxResponse-record)))

(defn pb->SpeculativeTxResponse
  "Protobuf to SpeculativeTxResponse"
  [input]
  (cis->SpeculativeTxResponse (serdes.stream/new-cis input)))

(def ^:protojure.protobuf.any/record SpeculativeTxResponse-meta {:type "com.xtdb.protos.SpeculativeTxResponse" :decoder pb->SpeculativeTxResponse})

Google code: com.google.protobuf/ecis->Struct

;-----------------------------------------------------------------------------
; Struct
;-----------------------------------------------------------------------------
(defrecord Struct-type [fields]
  pb/Writer

  (serialize [this os]
    (serdes.complex/write-map new-Struct-FieldsEntry 1 (:fields this) os)))

(s/def ::Struct-spec (s/keys :opt-un []))
(def Struct-defaults {:fields [] })

(defn cis->Struct
  "CodedInputStream to Struct"
  [is]
  (->> (tag-map Struct-defaults
         (fn [tag index]
             (case index
               1 [:fields (serdes.complex/cis->map ecis->Struct-FieldsEntry is)]

               [index (serdes.core/cis->undefined tag is)]))
         is)
        (map->Struct-type)))

(defn ecis->Struct
  "Embedded CodedInputStream to Struct"
  [is]
  (serdes.core/cis->embedded cis->Struct is))

(defn new-Struct
  "Creates a new instance from a map, similar to map->Struct except that
  it properly accounts for nested messages, when applicable.
  "
  [init]
  {:pre [(if (s/valid? ::Struct-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::Struct-spec init))))]}
  (-> (merge Struct-defaults init)
      (map->Struct-type)))

(defn pb->Struct
  "Protobuf to Struct"
  [input]
  (cis->Struct (serdes.stream/new-cis input)))

Split client and server generation

As it stands right now, the code generator emits both client and server code into one namespace. This results in conflicts that was resolved by adding a "call-" prefix to the client side code. This isn't ideal. Suggest splitting the client and server namespaces to avoid the conflict and thus retain the natural function names.

Why does the namespace require itself?

We're trying to use a protoc-gen-clojure-gen'd lib in our application, and the top-level namespace require includes the namespace itself. This doesn't cause problems on first load, but does cause problems when we try to reload the namespaces as a part of hot-reloading functionality.

Should the namespace be requiring itself? If so, why is it necessary (for my own edification)? If not, is that something that can safely be removed?

I can provide an example if desired.

Support v1.1.x protojure-lib

The latest protojure-lib has dropped support for size-XX operations in preparation for ClojureScript support. This patch ports the plugin to the latest protojure-lib by adjusting for the new namespaces and eliminating the size-XX calls

Golang fork behavior problem

Description

I'm trying to use the buf project to build a protobuf client that's hosted with their system. When I use protoc-gen-clojure as the target plugin, the command fails with:

Failure: plugin clojure: fork/exec /Users/me/.local/bin/protoc-gen-clojure: exec format error

This doesn't seem to be specific to buf, but rather to the packaging of the plugin:

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	fmt.Println(exec.Command("protoc-gen-clojure").Run())
}

produces the same error.

This happens with both the prebuilt 2.1.0 release and with a locally built binary based on most recent master.

Is there anything about jars that makes them incompatible with a fork call? If not, what would need to change to make this compatible with go tooling? It'd be nice to be able to use this plugin with buf.

Test configuration

Can you please include a test configuration for the resulting template? I have been trying to create a test but doesn't matter what I send it always return an empty body

Oneof convert-* field name collision

In 0.9.3 if two messages (A and B) have oneof fields with the same name (in this case: my_oneof), the generated code contains a single convert-my-oneof function for message: A but no convert-* function for message: B.

new-B calls A's convert-my-oneof function resulting in a B-record instance with missing fields.

syntax = "proto3";
package com.example.ab;

message A {
  oneof my_oneof {
    string s = 1;
    int32 i = 2;
  };
}

message B {
  oneof my_oneof {
    bool b = 1;
    float f = 2;
  };
}

Produces:

(defn convert-my-oneof [origkeyval]
  (cond
     (get-in origkeyval [:my-oneof :s]) origkeyval
     (get-in origkeyval [:my-oneof :i]) origkeyval
     :default origkeyval))

(defn new-A
  "Creates a new instance from a map, similar to map->A except that
  it properly accounts for nested messages, when applicable.
  "
  [init]
  {:pre [(if (s/valid? ::A-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::A-spec init))))]}
  (-> (merge A-defaults init)
      (convert-my-oneof)
      (map->A-record)))

(defn new-B
  "Creates a new instance from a map, similar to map->B except that
  it properly accounts for nested messages, when applicable.
  "
  [init]
  {:pre [(if (s/valid? ::B-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::B-spec init))))]}
  (-> (merge B-defaults init)
      (convert-my-oneof)
      (map->B-record)))

Oneof Fields with underscores not consistently rewritten with hiphens

diff --git a/resources/testdata/kitchensink.proto b/resources/testdata/kitchensink.proto
index 4b6e013..398a6c4 100755
--- a/resources/testdata/kitchensink.proto
+++ b/resources/testdata/kitchensink.proto
@@ -78,7 +78,7 @@ message OneOf {
         string s = 2;
         SimpleString ss = 3;
     }
-    oneof AndAnotherOne {
+    oneof AndAnother_One {
         string aas = 4;
         bool aab = 5;
         OEnum aae = 6;

leading to:

(defn write-AndAnother-One [AndAnother-One os]
  (let [field (first AndAnother-One)
        k (when-not (nil? field) (key field))
        v (when-not (nil? field) (val field))]
     (case k
         :aas (serdes.core/write-String 4  {:optimize false} v os)
         :aab (serdes.core/write-Bool 5  {:optimize false} v os)
         :aae (write-OEnum 6  {:optimize false} v os)
         nil)))
...
(defrecord OneOf-record [firsts One AndAnother-One seconds eo num e FinalOne]
  pb/Writer
  (serialize [this os]
    (serdes.core/write-String 1  {:optimize true} (:firsts this) os)
    (write-One  (:One this) os)
    (write-AndAnother_One  (:AndAnother-One this) os)
    (serdes.core/write-embedded 7 (:seconds this) os)
    (serdes.core/write-embedded 8 (:eo this) os)
    (serdes.core/write-Int32 9  {:optimize true} (:num this) os)
    (write-OEnum 10  {:optimize true} (:e this) os)
    (write-FinalOne  (:FinalOne this) os))
  pb/TypeReflection
  (gettype [this]
    "com.example.kitchensink.OneOf"))

this is probably an easy patch in the parse.oneof ns, but theres probably a way to hoist the clojurifying so that it only needs to be done once

option go_package bug

Given a foo.proto importing another bar.proto, if bar.proto uses a go_package option, the require of the bar ns in the foo ns will be output as [ :as ]

This is either related to our not ignoring go_package, or the CodeGenRequest including the go_package under a separate key that we don't ignore or handle properly.

Problem to generated proto when has java_package on proto files.

Hi, i'm having a problem with Clojure as a server and Golang as a client.
When my proto file contains the following lines:

syntax = "proto3";
package service.example.client;
option java_package = "br.com.service.example.client";

When we generate the server code, the generated code namespaces follows the java_package option, as expected.
However, the Golang client generated code doesn't follow the java_package naming convention, and instead, it tries to reach for methods declared on package service.example.client;

Because there's no namespaces declared as described above, the client fails to communicate with the server, and tells us that it couldn't find the implementation of the requested method.

To reproduce the problem, just follow the instructions on this repo: https://github.com/matheusfrancisco/issue-protoc-protojure-grpc

Would I like to know if his a bug on protojure side, if that's the case. I would like to help open a Pull Request as soon as possible?

imported namespaces need to respect package overrides

proto "import" statements refer to the proto "package", but the resulting import may have overridden the package with a language pragma, such as "java_package". This results in an incongruence between the generated :requires statement in the dependent code and the (ns) of the target.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.