Skip to content

Commit

Permalink
Merge pull request #40 from Medium/nick-inner
Browse files Browse the repository at this point in the history
Add fully qualified name to type descriptors, and resolve inner messages better
  • Loading branch information
nicks committed Oct 28, 2015
2 parents c342f76 + 746177e commit 3cd8f3c
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 15 deletions.
48 changes: 34 additions & 14 deletions lib/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,28 +203,45 @@ Project.prototype._processProto = function (fileName) {
proto.addImport(this._processProto(importName))
}, this)

this._resolveTypes(proto)
this._discoverTypes(proto, proto.getPackage())
this._resolveTypes(proto, proto.getPackage())
}
return proto
}


/**
* Resolve all protobuf types into the FieldDescriptors that name them.
* @param {ProtoDescriptor} proto
* Index all protobuf types
* @param {MessageDescriptor|ProtoDescriptor} proto
* @param {string} package
* @private
*/
Project.prototype._resolveTypes = function (proto) {
Project.prototype._discoverTypes = function (proto, package) {
proto.getMessages().forEach(function (message) {
var messageName = proto.getPackage() + '.' + message.getName()
message.setPackage(package)

var messageName = helper.joinPackage(package, message.getName())
this._typesByName[messageName] = message

this._discoverTypes(message, messageName)
}, this)

proto.getEnums().forEach(function (e) {
var eName = proto.getPackage() + '.' + e.getName()
e.setPackage(package)

var eName = helper.joinPackage(package, e.getName())
this._typesByName[eName] = e
}, this)
}


/**
* Resolve all protobuf types into the FieldDescriptors that name them.
* @param {MessageDescriptor|ProtoDescriptor} proto
* @param {string} package
* @private
*/
Project.prototype._resolveTypes = function (proto, package) {
proto.getMessages().forEach(function (message) {
message.getFields().forEach(function (field) {
if (field.isNativeType()) return
Expand All @@ -236,20 +253,23 @@ Project.prototype._resolveTypes = function (proto) {
return
}

if (typeName.indexOf('.') == -1) {
typeName = proto.getPackage() + '.' + typeName
}

var type = this._typesByName[typeName]
if (type) {
field.setTypeDescriptor(type)
return
var packageStack = package.split('.')
for (var i = 0; i <= packageStack.length; i++) {
var scope = packageStack.slice(0, i).join('.')
var globalTypeName = helper.joinPackage(scope, typeName)
var type = this._typesByName[globalTypeName]
if (type) {
field.setTypeDescriptor(type)
return
}
}

throw new Error('Could not resolve type of field ' + field.getName() +
' on message ' + message.getName() +
' : ' + field.getRawType())
}, this)

this._resolveTypes(message, helper.joinPackage(package, message.getName()))
}, this)
}

Expand Down
8 changes: 8 additions & 0 deletions lib/descriptors/EnumDescriptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function EnumDescriptor(name) {
this._name = name
this._numbers = {}
this._names = {}
this._package = ''
}
util.inherits(EnumDescriptor, Descriptor)
module.exports = EnumDescriptor
Expand All @@ -34,13 +35,20 @@ EnumDescriptor.prototype.toTemplateObject = function () {
numbers.sort()
return {
name: this._name,
fullName: helper.joinPackage(this._package, this._name),
values: numbers.map(function (n) {
return this.getValueForNumber(n)
}, this),
isEnum: true
}
}


EnumDescriptor.prototype.setPackage = function (package) {
this._package = package
}


EnumDescriptor.prototype.getName = function () {
return this._name
}
Expand Down
12 changes: 12 additions & 0 deletions lib/descriptors/MessageDescriptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function MessageDescriptor(name) {
this._enums = {}
this._fields = {}
this._fieldNames = {}
this._package = ''
}
util.inherits(MessageDescriptor, Descriptor)
module.exports = MessageDescriptor
Expand All @@ -40,6 +41,7 @@ MessageDescriptor.prototype.inspect = function () {
MessageDescriptor.prototype.toTemplateObject = function (opt_skipFields) {
var obj = {
name: this._name,
fullName: helper.joinPackage(this._package, this._name),
camelName: this.getCamelName(),
options: this._options
}
Expand All @@ -54,6 +56,11 @@ MessageDescriptor.prototype.toTemplateObject = function (opt_skipFields) {
}


MessageDescriptor.prototype.setPackage = function (package) {
this._package = package
}


MessageDescriptor.prototype.addOption = function (name, value) {
this._options[name] = value
return this
Expand Down Expand Up @@ -158,6 +165,11 @@ MessageDescriptor.prototype.addEnum = function (enumeration) {
}


MessageDescriptor.prototype.getEnums = function () {
return helper.values(this._enums)
}


MessageDescriptor.prototype.getEnum = function (name) {
return this._enums[name]
}
Expand Down
10 changes: 10 additions & 0 deletions lib/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,13 @@ exports.mkdir = function(name) {
mkdirp(dir, deferred.makeNodeResolver())
return deferred.promise
}

/**
* Join a package to a name, where the package may be the default package.
* @param {string} package
* @param {string} name
* @return {string}
*/
exports.joinPackage = function (package, name) {
return package ? (package + '.' + name) : name
}
16 changes: 15 additions & 1 deletion tests/project_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ builder.add(function testGetProtos(test) {
{name: 'HOME', titleName: 'Home', number: 1},
{name: 'WORK', titleName: 'Work', number: 2},
{name: 'WORK_FAX', titleName: 'WorkFax', number: 3}],
isEnum: true},
isEnum: true, fullName: 'examples.Person.PhoneType'},
enums[0])

test.done()
Expand Down Expand Up @@ -124,6 +124,7 @@ builder.add(function testRemoveField(test) {
.addProto('protos/common.proto')

var color = project.getProtos('protos/common.proto')[0].getMessage('Color')
console.log('COLOR', color.toTemplateObject)
test.equal(3, color.toTemplateObject().fields.length)

color.removeFieldByName('red')
Expand All @@ -141,6 +142,19 @@ builder.add(function testTypeResolution(test) {
test.done()
})

builder.add(function testTypeResolutionInner(test) {
var project = new Project(baseDir)
.addProto('protos/inner.proto')

var tortilla = project.getProtos('protos/inner.proto')[0].getMessage('Tortilla')
var tortillaJson = tortilla.toTemplateObject()
test.equal('burrito.Tortilla.Filling', tortillaJson.fields[0].typeDescriptor.fullName)
test.equal('burrito.Tortilla.Filling', tortillaJson.fields[1].typeDescriptor.fullName)
test.equal('burrito.Tortilla.Guac', tortillaJson.fields[2].typeDescriptor.fullName)
test.equal('burrito.Tortilla.Guac', tortillaJson.fields[3].typeDescriptor.fullName)
test.done()
})

builder.add(function testTypeResolutionLoop(test) {
var project = new Project(baseDir)
.addProto('protos/loop.proto')
Expand Down
21 changes: 21 additions & 0 deletions tests/protos/inner.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package burrito;

message Tortilla {
enum Filling {
CHICKEN = 1;
BEEF = 2;
TOFU = 3;
}

message Guac {
repeated Avocado avacados = 1;
}

optional Filling filling1 = 2;
optional burrito.Tortilla.Filling filling2 = 3;
optional Guac guac1 = 4;
optional burrito.Tortilla.Guac guac2 = 5;
}

message Avocado {
}

0 comments on commit 3cd8f3c

Please sign in to comment.