Skip to content

Commit

Permalink
Other: Added infrastructure for TypeScript support of extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO committed Apr 12, 2017
1 parent 57d7d35 commit 708552b
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 99 deletions.
1 change: 0 additions & 1 deletion cli/lib/tsd-jsdoc/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,6 @@ function notAModuleReference(ref) {
return ref.indexOf("module:") === -1;
}


// handles a class or class-like
function handleClass(element, parent) {
var is_interface = isInterface(element);
Expand Down
2 changes: 1 addition & 1 deletion cli/targets/static.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ function buildType(ref, type) {
"@constructor",
"@param {" + fullName + "$Properties=} [" + (config.beautify ? "properties" : "p") + "] Properties to set"
]);
buildFunction(type, type.name, Class.generate(type));
buildFunction(type, type.name, Type.generateConstructor(type));

// default values
var firstField = true;
Expand Down
21 changes: 21 additions & 0 deletions ext/descriptor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
protobufjs/ext/descriptor
=========================

Experimental [protobuf.js](https://github.com/dcodeIO/protobuf.js) extension for interoperability with descriptor.proto types.

Usage
-----

```js
var protobuf = require("protobufjs"),
descriptor = require("protobufjs/ext/descriptor");

var descriptor = ...; // either a FieldDescriptorSet buffer or JSON object
var root = protobuf.Root.fromDescriptor(descriptor);
var rootDescriptor = root.toDescriptor("proto3");
```

API
---

The extension adds `.fromDescriptor(descriptor[, syntax])` and `#toDescriptor([syntax])` methods to reflection objects and exports the internally used `Root` instance that contains the types present in descriptor.proto.
108 changes: 108 additions & 0 deletions ext/descriptor/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import * as $protobuf from "../..";

declare const descriptor: $protobuf.Root;

interface IFileDescriptorSet {
file: IFileDescriptorProto[];
}

interface IFileDescriptorProto {
name?: string;
package?: string;
dependency?: any;
publicDependency?: any;
weakDependency?: any;
messageType?: IDescriptorProto[];
enumType?: IEnumDescriptorProto[];
service?: IServiceDescriptorProto[];
extension?: IFieldDescriptorProto[];
options?: any;
sourceCodeInfo?: any;
syntax?: string;
}

interface IDescriptorProto {
name?: string;
field?: IFieldDescriptorProto[];
extension?: IFieldDescriptorProto[];
nestedType?: IDescriptorProto[];
enumType?: IEnumDescriptorProto[];
extensionRange?: IExtensionRange[];
oneofDecl?: IOneofDescriptorProto[];
options?: IMessageOptions;
reservedRange?: IReservedRange[];
reservedName?: string[];
}

interface IMessageOptions {
mapEntry?: any;
}

interface IExtensionRange {
start?: number;
end?: number;
}

interface IReservedRange {
start?: number;
end?: number;
}

interface IFieldDescriptorProto {
name?: string;
number?: number;
label?: IFieldDescriptorProto_Label;
type?: IFieldDescriptorProto_Type;
typeName?: string;
extendee?: string;
defaultValue?: any;
oneofIndex?: number;
jsonName?: any;
options?: IFieldOptions;
}

type IFieldDescriptorProto_Label = number;

type IFieldDescriptorProto_Type = number;

interface IFieldOptions {
packed?: boolean;
}

interface IEnumDescriptorProto {
name?: string;
value?: IEnumValueDescriptorProto[];
options?: IEnumOptions;
}

interface IEnumValueDescriptorProto {
name?: string;
number?: number;
options?: any;
}

interface IEnumOptions {
allowAlias?: boolean;
}

interface IOneofDescriptorProto {
name?: string;
options?: any;
}

interface IServiceDescriptorProto {
name?: string;
method?: IMethodDescriptorProto[];
options?: any;
}

interface IMethodDescriptorProto {
name?: string;
inputType?: string;
outputType?: string;
options?: any;
clientStreaming?: boolean;
serverStreaming?: boolean;
}

export = descriptor;
95 changes: 18 additions & 77 deletions ext/descriptor.js → ext/descriptor/index.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
// [WIP] Extension for reflection interoperability with descriptor.proto types
// var protobuf = require("protobufjs"),
// descriptor = require("protobufjs/ext/descriptor");
// ...
"use strict";

var protobuf = require("..");
var $protobuf = require("..");

/**
* Descriptor extension (ext/descriptor).
* @namespace
* @type {Root}
* @tstype $protobuf.Root
* @const
*/

var descriptor = module.exports = protobuf.Root.fromJSON(require("../google/protobuf/descriptor.json")).lookup(".google.protobuf");
var descriptor = module.exports = $protobuf.Root.fromJSON(require("../google/protobuf/descriptor.json")).lookup(".google.protobuf");

var google = descriptor,
Root = protobuf.Root,
Enum = protobuf.Enum,
Type = protobuf.Type,
Field = protobuf.Field,
OneOf = protobuf.OneOf,
Service = protobuf.Service,
Method = protobuf.Method;
Root = $protobuf.Root,
Enum = $protobuf.Enum,
Type = $protobuf.Type,
Field = $protobuf.Field,
OneOf = $protobuf.OneOf,
Service = $protobuf.Service,
Method = $protobuf.Method;

// --- Root ---

/**
* Reflected type describing a root.
* @name descriptor.FileDescriptorSet
* @type {Type}
*/

/**
* @interface IFileDescriptorSet
* @property {IFileDescriptorProto[]} file
Expand Down Expand Up @@ -118,12 +109,6 @@ Root.prototype.toDescriptor = function toDescriptor(syntax) {

// --- Type ---

/**
* Reflected type describing a type.
* @name descriptor.DescriptorProto
* @type {Type}
*/

/**
* @interface IDescriptorProto
* @property {string} [name]
Expand Down Expand Up @@ -175,15 +160,15 @@ Type.fromDescriptor = function fromDescriptor(descriptor, syntax) {
i;

/* Fields */ for (i = 0; i < descriptor.field.length; ++i)
type.add(protobuf.Field.fromDescriptor(descriptor.field[i], syntax));
type.add(Field.fromDescriptor(descriptor.field[i], syntax));
/* Extension fields */ for (i = 0; i < descriptor.extension.length; ++i)
type.add(protobuf.Field.fromDescriptor(descriptor.extension[i], syntax));
type.add(Field.fromDescriptor(descriptor.extension[i], syntax));
/* Oneofs */ for (i = 0; i < descriptor.oneofDecl.length; ++i)
type.add(protobuf.OneOf.fromDescriptor(descriptor.oneofDecl[i]));
type.add(OneOf.fromDescriptor(descriptor.oneofDecl[i]));
/* Nested types */ for (i = 0; i < descriptor.nestedType.length; ++i)
type.add(protobuf.Type.fromDescriptor(descriptor.nestedType[i], syntax));
type.add(Type.fromDescriptor(descriptor.nestedType[i], syntax));
/* Nested enums */ for (i = 0; i < descriptor.enumType.length; ++i)
type.add(protobuf.Enum.fromDescriptor(descriptor.enumType[i]));
type.add(Enum.fromDescriptor(descriptor.enumType[i]));
/* Extension ranges */ if (descriptor.extensionRange.length) {
type.extensions = [];
for (i = 0; i < descriptor.extensionRange.length; ++i)
Expand Down Expand Up @@ -236,18 +221,10 @@ Type.prototype.toDescriptor = function toDescriptor(syntax) {

// --- Field ---

/**
* Reflected type describing a field.
* @name descriptor.FieldDescriptorProto
* @type {Type}
* @property {Enum} Label Reflected descriptor describing a field label (rule)
* @property {Enum} Type Reflected descriptor describing a field type
*/

/**
* @interface IFieldDescriptorProto
* @property {string} [name]
* @property {number} [number}
* @property {number} [number]
* @property {IFieldDescriptorProto_Label} [label]
* @property {IFieldDescriptorProto_Type} [type]
* @property {string} [typeName]
Expand Down Expand Up @@ -424,24 +401,6 @@ Field.prototype.toDescriptor = function toDescriptor(syntax) {

// --- Enum ---

/**
* Reflected type describing an enum.
* @name descriptor.EnumDescriptorProto
* @type {Type}
*/

/**
* Reflected type describing an enum value.
* @name descriptor.EnumValueDescriptorProto
* @type {Type}
*/

/**
* Reflected type describing enum options.
* @name descriptor.EnumOptions
* @type {Type}
*/

/**
* @interface IEnumDescriptorProto
* @property {string} [name]
Expand Down Expand Up @@ -511,12 +470,6 @@ Enum.prototype.toDescriptor = function toDescriptor() {

// --- OneOf ---

/**
* Reflected type describing a oneof.
* @name descriptor.OneofDescriptorProto
* @type {Type}
*/

/**
* @interface IOneofDescriptorProto
* @property {string} [name]
Expand Down Expand Up @@ -556,12 +509,6 @@ OneOf.prototype.toDescriptor = function toDescriptor() {

// --- Service ---

/**
* Reflected type describing a service.
* @name descriptor.ServiceDescriptorProto
* @type {Type}
*/

/**
* @interface IServiceDescriptorProto
* @property {string} [name]
Expand Down Expand Up @@ -610,12 +557,6 @@ Service.prototype.toDescriptor = function toDescriptor() {

// --- Method ---

/**
* Reflected type describing a method.
* @name descriptor.MethodDescriptorProto
* @type {Type}
*/

/**
* @interface IMethodDescriptorProto
* @property {string} [name]
Expand Down
7 changes: 7 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,13 @@ export class Type extends NamespaceBase {
*/
public ctor: Constructor<{}>;

/**
* Generates a constructor function for the specified type.
* @param {Type} type Type
* @returns {Codegen} Codegen instance
*/
public static generateConstructor(type: Type): Codegen;

/**
* Creates a message type from a message type descriptor.
* @param {string} name Message name
Expand Down
17 changes: 12 additions & 5 deletions scripts/gentests.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ var fs = require("fs"),
});

[
"tests/data/rpc.js",
"tests/data/test.js",
{ file: "tests/data/rpc.js" },
{ file: "tests/data/test.js" },
{ file: "ext/descriptor/index.js", ext: true }
]
.forEach(function(file) {
.forEach(function({ file, ext }) {
var out = file.replace(/\.js$/, ".d.ts");
pbts.main([
"--no-comments",
Expand All @@ -54,7 +55,13 @@ var fs = require("fs"),
if (err)
throw err;
var pathToProtobufjs = path.relative(path.dirname(out), "").replace(/\\/g, "/");
fs.writeFileSync(out, output.replace(/"protobufjs"/g, JSON.stringify(pathToProtobufjs)));
output = output.replace(/"protobufjs"/g, JSON.stringify(pathToProtobufjs));
if (ext) {
var extName;
output = output.replace(/export (\w+) (\w+)/, function($0, $1, $2) { extName = $2; return "declare " + $1 + " " + extName; });
output += "\nexport = " + extName + ";\n";
}
fs.writeFileSync(out, output);
process.stdout.write("pbts: " + file + " -> " + out + "\n");
});
});
});
11 changes: 8 additions & 3 deletions src/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Object.defineProperties(Type.prototype, {
*/
ctor: {
get: function() {
return this._ctor || (this.ctor = generateConstructor(this).eof(this.name));
return this._ctor || (this.ctor = Type.generateConstructor(this).eof(this.name));
},
set: function(ctor) {

Expand Down Expand Up @@ -189,7 +189,12 @@ Object.defineProperties(Type.prototype, {
}
});

function generateConstructor(type) {
/**
* Generates a constructor function for the specified type.
* @param {Type} type Type
* @returns {Codegen} Codegen instance
*/
Type.generateConstructor = function generateConstructor(type) {
/* eslint-disable no-unexpected-multiline */
var gen = util.codegen("p");
// explicitly initialize mutable object/array fields so that these aren't just inherited from the prototype
Expand All @@ -202,7 +207,7 @@ function generateConstructor(type) {
("if(p)for(var ks=Object.keys(p),i=0;i<ks.length;++i)if(p[ks[i]]!=null)") // omit undefined or null
("this[ks[i]]=p[ks[i]]");
/* eslint-enable no-unexpected-multiline */
}
};

function clearCache(type) {
type._fieldsById = type._fieldsArray = type._oneofsArray = type._ctor = null;
Expand Down
Loading

0 comments on commit 708552b

Please sign in to comment.