|
"use strict"; |
|
module.exports = ReflectionObject; |
|
|
|
ReflectionObject.className = "ReflectionObject"; |
|
|
|
const OneOf = require("./oneof"); |
|
var util = require("./util"); |
|
|
|
var Root; |
|
|
|
|
|
|
|
var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"}; |
|
var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE"}; |
|
var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY"}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function ReflectionObject(name, options) { |
|
|
|
if (!util.isString(name)) |
|
throw TypeError("name must be a string"); |
|
|
|
if (options && !util.isObject(options)) |
|
throw TypeError("options must be an object"); |
|
|
|
|
|
|
|
|
|
|
|
this.options = options; |
|
|
|
|
|
|
|
|
|
|
|
this.parsedOptions = null; |
|
|
|
|
|
|
|
|
|
|
|
this.name = name; |
|
|
|
|
|
|
|
|
|
|
|
this._edition = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
this._defaultEdition = "proto2"; |
|
|
|
|
|
|
|
|
|
|
|
this._features = {}; |
|
|
|
|
|
|
|
|
|
|
|
this.parent = null; |
|
|
|
|
|
|
|
|
|
|
|
this.resolved = false; |
|
|
|
|
|
|
|
|
|
|
|
this.comment = null; |
|
|
|
|
|
|
|
|
|
|
|
this.filename = null; |
|
} |
|
|
|
Object.defineProperties(ReflectionObject.prototype, { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
root: { |
|
get: function() { |
|
var ptr = this; |
|
while (ptr.parent !== null) |
|
ptr = ptr.parent; |
|
return ptr; |
|
} |
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fullName: { |
|
get: function() { |
|
var path = [ this.name ], |
|
ptr = this.parent; |
|
while (ptr) { |
|
path.unshift(ptr.name); |
|
ptr = ptr.parent; |
|
} |
|
return path.join("."); |
|
} |
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.toJSON = function toJSON() { |
|
throw Error(); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.onAdd = function onAdd(parent) { |
|
if (this.parent && this.parent !== parent) |
|
this.parent.remove(this); |
|
this.parent = parent; |
|
this.resolved = false; |
|
var root = parent.root; |
|
if (root instanceof Root) |
|
root._handleAdd(this); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.onRemove = function onRemove(parent) { |
|
var root = parent.root; |
|
if (root instanceof Root) |
|
root._handleRemove(this); |
|
this.parent = null; |
|
this.resolved = false; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.resolve = function resolve() { |
|
if (this.resolved) |
|
return this; |
|
if (this instanceof Root) { |
|
this._resolveFeaturesRecursive(this._edition); |
|
this.resolved = true; |
|
} |
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) { |
|
return this._resolveFeatures(this._edition || edition); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) { |
|
var defaults = {}; |
|
|
|
|
|
if (!edition) { |
|
throw new Error("Unknown edition for " + this.fullName); |
|
} |
|
|
|
var protoFeatures = Object.assign(this.options ? Object.assign({}, this.options.features) : {}, |
|
this._inferLegacyProtoFeatures(edition)); |
|
|
|
if (this._edition) { |
|
|
|
|
|
if (edition === "proto2") { |
|
defaults = Object.assign({}, proto2Defaults); |
|
} else if (edition === "proto3") { |
|
defaults = Object.assign({}, proto3Defaults); |
|
} else if (edition === "2023") { |
|
defaults = Object.assign({}, editions2023Defaults); |
|
} else { |
|
throw new Error("Unknown edition: " + edition); |
|
} |
|
this._features = Object.assign(defaults, protoFeatures || {}); |
|
return; |
|
} |
|
|
|
|
|
|
|
|
|
if (this.partOf instanceof OneOf) { |
|
var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features); |
|
this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {}); |
|
} else if (this.declaringField) { |
|
|
|
} else if (this.parent) { |
|
var parentFeaturesCopy = Object.assign({}, this.parent._features); |
|
this._features = Object.assign(parentFeaturesCopy, protoFeatures || {}); |
|
} else { |
|
throw new Error("Unable to find a parent for " + this.fullName); |
|
} |
|
if (this.extensionField) { |
|
|
|
this.extensionField._features = this._features; |
|
} |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures() { |
|
return {}; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.getOption = function getOption(name) { |
|
if (this.options) |
|
return this.options[name]; |
|
return undefined; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) { |
|
if (!this.options) |
|
this.options = {}; |
|
if (/^features\./.test(name)) { |
|
util.setProperty(this.options, name, value, ifNotSet); |
|
} else if (!ifNotSet || this.options[name] === undefined) { |
|
if (this.getOption(name) !== value) this.resolved = false; |
|
this.options[name] = value; |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.setParsedOption = function setParsedOption(name, value, propName) { |
|
if (!this.parsedOptions) { |
|
this.parsedOptions = []; |
|
} |
|
var parsedOptions = this.parsedOptions; |
|
if (propName) { |
|
|
|
|
|
var opt = parsedOptions.find(function (opt) { |
|
return Object.prototype.hasOwnProperty.call(opt, name); |
|
}); |
|
if (opt) { |
|
|
|
|
|
var newValue = opt[name]; |
|
util.setProperty(newValue, propName, value); |
|
} else { |
|
|
|
opt = {}; |
|
opt[name] = util.setProperty({}, propName, value); |
|
parsedOptions.push(opt); |
|
} |
|
} else { |
|
|
|
var newOpt = {}; |
|
newOpt[name] = value; |
|
parsedOptions.push(newOpt); |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.setOptions = function setOptions(options, ifNotSet) { |
|
if (options) |
|
for (var keys = Object.keys(options), i = 0; i < keys.length; ++i) |
|
this.setOption(keys[i], options[keys[i]], ifNotSet); |
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype.toString = function toString() { |
|
var className = this.constructor.className, |
|
fullName = this.fullName; |
|
if (fullName.length) |
|
return className + " " + fullName; |
|
return className; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
ReflectionObject.prototype._editionToJSON = function _editionToJSON() { |
|
if (!this._edition || this._edition === "proto3") { |
|
|
|
|
|
return undefined; |
|
} |
|
return this._edition; |
|
}; |
|
|
|
|
|
ReflectionObject._configure = function(Root_) { |
|
Root = Root_; |
|
}; |
|
|