]> asedeno.scripts.mit.edu Git - cl-protobufs.git/commitdiff
Still better support for qualified names:
authorScott McKay <swm@google.com>
Mon, 18 Jun 2012 15:00:19 +0000 (15:00 +0000)
committerScott McKay <swm@google.com>
Mon, 18 Jun 2012 15:00:19 +0000 (15:00 +0000)
 - Add 'make-qualified-name' function that knows how to prepend
   message and package names.
 - All the places that create messages, enums, fields, etc, now
   generate a qualified name.
 - 'find-qualified-name' now thoroughly checks the qualified name.

Passes 'precheckin' with the new Protobufs unit tests in place.

git-svn-id: http://svn.internal.itasoftware.com/svn/ita/trunk/qres/lisp/libs/cl-protobufs@549563 f8382938-511b-0410-9cdd-bb47b084005c

define-proto.lisp
model-classes.lisp
parser.lisp
utilities.lisp

index ff78c5a514e63c489f2ee5497eb9a69b39098880..79918e06809d445cde107775437bc6f9643b1df7 100644 (file)
          (enum  (make-instance 'protobuf-enum
                   :class  type
                   :name   name
+                  :qualified-name (make-qualified-name *protobuf* name)
                   :alias-for alias-for
                   :options options
                   :documentation documentation)))
          (message (make-instance 'protobuf-message
                     :class type
                     :name  name
+                    :qualified-name (make-qualified-name *protobuf* name)
                     :parent *protobuf*
                     :alias-for alias-for
                     :conc-name conc-name
                        (make-instance 'protobuf-message
                          :class  type
                          :name   name
+                         :qualified-name (make-qualified-name *protobuf* name)
                          :parent (proto-parent message)
                          :alias-for alias-for
                          :conc-name conc-name
                     :name  (slot-name->proto slot)
                     :type  name
                     :class type
+                    :qualified-name (make-qualified-name *protobuf* (slot-name->proto slot))
                     :required arity
                     :index index
                     :value slot
          (message (make-instance 'protobuf-message
                     :class type
                     :name  name
+                    :qualified-name (make-qualified-name *protobuf* name)
                     :alias-for alias-for
                     :conc-name conc-name
                     :options   (remove-options options "default" "packed")
                           :name  (or name (slot-name->proto slot))
                           :type  ptype
                           :class pclass
+                          :qualified-name (make-qualified-name *protobuf* (or name (slot-name->proto slot)))
                           ;; One of :required, :optional or :repeated
                           :required reqd
                           :index  idx
          (service (make-instance 'protobuf-service
                     :class type
                     :name  name
+                    :qualified-name (make-qualified-name *protobuf* name)
                     :options options
                     :documentation documentation))
          (index 0))
                  (method  (make-instance 'protobuf-method
                             :class function
                             :name  (or name (class-name->proto function))
+                            :qualified-name (make-qualified-name *protobuf* (or name (class-name->proto function)))
                             :client-stub client-fn
                             :server-stub server-fn
                             :input-type  input-type
index e871b4cdfc6e32c28e32c5dec608615a65c5ec81..be000e3044f7b2386f1c65e8f6ce24ec9afa483c 100644 (file)
@@ -48,7 +48,7 @@
 
 ;; A few things (the pretty printer) want to keep track of the current schema
 (defvar *protobuf* nil
-  "The Protobufs object currently being defined, e.g., a schema, a message, etc.")
+  "The Protobufs object currently being defined, either a schema or a message.")
 
 (defvar *protobuf-package* nil
   "The Lisp package in which the Protobufs schema is being defined.")
          :reader proto-name
          :initarg :name
          :initform nil)
-   (full-name :type (or null string)            ;the fully qualified name, e.g., "proto2.MessageSet"
+   (qual-name :type string                      ;the fully qualified name, e.g., "proto2.MessageSet"
               :accessor proto-qualified-name
               :initarg :qualified-name
-              :initform nil)
+              :initform "")
    (options :type (list-of protobuf-option)     ;options, mostly just passed along
             :accessor proto-options
             :initarg :options
    "The base class for all Protobufs model classes."))
 
 (defun find-qualified-name (name protos
-                            &key (proto-key #'proto-name) (lisp-key #'proto-class))
+                            &key (proto-key #'proto-name) (full-key #'proto-qualified-name)
+                                 (lisp-key #'proto-class))
   "Find something by its string name.
    First do a simple name match.
    Failing that, exhaustively search qualified names."
   (or (find name protos :key proto-key :test #'string=)
+      (find name protos :key full-key  :test #'string=)
       ;; Get desperate in the face of incomplete namespace support
       ;;--- This needs to be more sophisticated than just using Lisp packages
       (multiple-value-bind (name package path other)
             :accessor proto-package
             :initarg :package
             :initform nil)
-   (lisp-pkg :type (or null string)              ;the Lisp package, from 'option lisp_package = ...'
+   (lisp-pkg :type (or null string)             ;the Lisp package, from 'option lisp_package = ...'
              :accessor proto-lisp-package
              :initarg :lisp-package
              :initform nil)
     (format stream "~@[~S~]~@[ (package ~A)~]"
             (proto-class s) (proto-package s))))
 
+(defgeneric make-qualified-name (proto name)
+  (:documentation
+   "Give a schema or message and a name,
+    generate a fully qualified name string for the name."))
+
+(defmethod make-qualified-name ((schema protobuf-schema) name)
+  ;; If we're at the parent, the qualified name is the schema's
+  ;; packaged "dot" the name
+  (strcat (proto-package schema) "." name))
+
 (defgeneric find-enum (protobuf type)
   (:documentation
    "Given a Protobufs schema or message and the name of an enum type,
                  :accessor proto-message-type
                  :initarg :message-type
                  :initform :message))
-    (:documentation
+  (:documentation
    "The model class that represents a Protobufs message."))
 
 (defmethod make-load-form ((m protobuf-message) &optional environment)
             (eq (proto-message-type m) :group)
             (eq (proto-message-type m) :extends))))
 
+(defmethod proto-package ((message protobuf-message))
+  (and (proto-parent message)
+       (proto-package (proto-parent message))))
+
+(defmethod proto-lisp-package ((message protobuf-message))
+  (and (proto-parent message)
+       (proto-lisp-package (proto-parent message))))
+
+(defmethod make-qualified-name ((message protobuf-message) name)
+  ;; If there's a parent for this message (there should be -- the schema),
+  ;; make a partially qualified name of message name "dot" name, then
+  ;; ask the parent to add its own qualifiers
+  (if (proto-parent message)
+    (make-qualified-name (proto-parent message) (strcat (proto-name message) "." name))
+    (strcat (proto-name message) "." name)))
+
 (defmethod find-message ((message protobuf-message) (type symbol))
   ;; Extended messages "shadow" non-extended ones
   (or (find type (proto-extenders message) :key #'proto-class)
index ed1505e2016b8e61d6a2ffbe1816207ac78fa98e..e207606a2ff152ed55b42d2ad3d97901f72e737b 100644 (file)
                  (maybe-skip-comments stream)))
          (enum (make-instance 'protobuf-enum
                  :class (proto->class-name name *protobuf-package*)
-                 :name name)))
+                 :name name
+                 :qualified-name (make-qualified-name protobuf name))))
     (loop
       (let ((name (parse-token stream)))
         (when (null name)
          (class (proto->class-name name *protobuf-package*))
          (message (make-instance 'protobuf-message
                     :class class
-                    :name name
+                    :name  name
+                    :qualified-name (make-qualified-name protobuf name)
                     :parent protobuf
                     ;; Maybe force accessors for all slots
                     :conc-name (conc-name-for-type class *protobuf-conc-name*)))
          (message (find-message protobuf name))
          (extends (and message
                        (make-instance 'protobuf-message
-                         :class  (proto->class-name name *protobuf-package*)
-                         :name   name
+                         :class (proto->class-name name *protobuf-package*)
+                         :name  name
+                         :qualified-name (make-qualified-name protobuf name)
                          :parent (proto-parent message)
                          :conc-name (proto-conc-name message)
                          :alias-for (proto-alias-for message)
                        :name  name
                        :type  type
                        :class class
+                       :qualified-name (make-qualified-name message name)
                        ;; One of :required, :optional or :repeated
                        :required reqd
                        :index idx
                   :name  name
                   :type  type
                   :class class
+                  :qualified-name (make-qualified-name message name)
                   :required (kintern required)
                   :index idx
                   :value slot
                  (maybe-skip-comments stream)))
          (service (make-instance 'protobuf-service
                     :class (proto->class-name name *protobuf-package*)
-                    :name name))
+                    :name name
+                    :qualified-name (make-qualified-name *protobuf* name)))
          (index 0))
     (loop
       (let ((token (parse-token stream)))
          (method (make-instance 'protobuf-method
                    :class stub
                    :name  name
+                   :qualified-name (make-qualified-name *protobuf* name)
                    :input-type  (proto->class-name in *protobuf-package*)
                    :input-name  in
                    :output-type (proto->class-name out *protobuf-package*)
index 48b192f8414f16ec2fe4d2a7cd1890b0e933a665..62e904332f801e292ce678d033a44bf6e67f7919 100644 (file)
        (string-equal string suffix :start1 (i- end (length suffix)) :end1 end)
        suffix))
 
+(defun strcat (&rest strings)
+  "Concatenate a bunch of strings."
+  (declare (dynamic-extent strings))
+  (apply #'concatenate 'string strings))
+
 
 ;; (camel-case "camel-case") => "CamelCase"
 (defun camel-case (string &optional (separators '(#\-)))
                                (cons #\. result)))
                      (t
                       (error "Invalid name character: ~A" ch))))))
-    (concatenate 'string (nreverse (uncamel (concatenate 'list name) nil ())))))
+    (strcat (nreverse (uncamel (concatenate 'list name) nil ())))))
 
 
 (defun split-string (line &key (start 0) (end (length line)) (separators '(#\-)))