43
44
#include <google/protobuf/descriptor_database.h>
44
45
#include <google/protobuf/descriptor.pb.h>
45
46
#include <google/protobuf/dynamic_message.h>
47
#include <google/protobuf/generated_message_util.h>
46
48
#include <google/protobuf/text_format.h>
47
49
#include <google/protobuf/unknown_field_set.h>
48
50
#include <google/protobuf/wire_format.h>
51
#include <google/protobuf/io/strtod.h>
49
52
#include <google/protobuf/io/coded_stream.h>
50
53
#include <google/protobuf/io/tokenizer.h>
51
54
#include <google/protobuf/io/zero_copy_stream_impl.h>
239
NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
246
NULL_SYMBOL, MESSAGE, FIELD, ONEOF, ENUM, ENUM_VALUE, SERVICE, METHOD,
244
251
const Descriptor* descriptor;
245
252
const FieldDescriptor* field_descriptor;
253
const OneofDescriptor* oneof_descriptor;
246
254
const EnumDescriptor* enum_descriptor;
247
255
const EnumValueDescriptor* enum_value_descriptor;
248
256
const ServiceDescriptor* service_descriptor;
269
277
CONSTRUCTOR(Descriptor , MESSAGE , descriptor )
270
278
CONSTRUCTOR(FieldDescriptor , FIELD , field_descriptor )
279
CONSTRUCTOR(OneofDescriptor , ONEOF , oneof_descriptor )
271
280
CONSTRUCTOR(EnumDescriptor , ENUM , enum_descriptor )
272
281
CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor )
273
282
CONSTRUCTOR(ServiceDescriptor , SERVICE , service_descriptor )
370
380
vector<string> pending_files_;
372
382
// A set of files which we have tried to load from the fallback database
373
// and encountered errors. We will not attempt to load them again.
383
// and encountered errors. We will not attempt to load them again during
384
// execution of the current public API call, but for compatibility with
385
// legacy clients, this is cleared at the beginning of each public API call.
374
386
// Not used when fallback_database_ == NULL.
375
387
hash_set<string> known_bad_files_;
389
// A set of symbols which we have tried to load from the fallback database
390
// and encountered errors. We will not attempt to load them again during
391
// execution of the current public API call, but for compatibility with
392
// legacy clients, this is cleared at the beginning of each public API call.
393
hash_set<string> known_bad_symbols_;
377
395
// The set of descriptors for which we've already loaded the full
378
396
// set of extensions numbers from fallback_database_.
379
397
hash_set<const Descriptor*> extensions_loaded_from_db_;
531
549
// fails because we allow duplicates; the first field by the name wins.
532
550
void AddFieldByStylizedNames(const FieldDescriptor* field);
552
// Populates p->first->locations_by_path_ from p->second.
553
// Unusual signature dictated by GoogleOnceDynamic.
554
static void BuildLocationsByPath(
555
pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
557
// Returns the location denoted by the specified path through info,
558
// or NULL if not found.
559
// The value of info must be that of the corresponding FileDescriptor.
560
// (Conceptually a pure function, but stateful as an optimisation.)
561
const SourceCodeInfo_Location* GetSourceLocation(
562
const vector<int>& path, const SourceCodeInfo* info) const;
535
565
SymbolsByParentMap symbols_by_parent_;
536
566
FieldsByNameMap fields_by_lowercase_name_;
537
567
FieldsByNameMap fields_by_camelcase_name_;
538
568
FieldsByNumberMap fields_by_number_; // Not including extensions.
539
569
EnumValuesByNumberMap enum_values_by_number_;
571
// Populated on first request to save space, hence constness games.
572
mutable GoogleOnceDynamic locations_by_path_once_;
573
mutable LocationsByPathMap locations_by_path_;
542
576
DescriptorPool::Tables::Tables()
543
577
// Start some hash_map and hash_set objects with a small # of buckets
544
578
: known_bad_files_(3),
579
known_bad_symbols_(3),
545
580
extensions_loaded_from_db_(3),
546
581
symbols_by_name_(3),
547
582
files_by_name_(3) {}
667
702
Symbol DescriptorPool::Tables::FindByNameHelper(
668
const DescriptorPool* pool, const string& name) const {
703
const DescriptorPool* pool, const string& name) {
669
704
MutexLockMaybe lock(pool->mutex_);
705
known_bad_symbols_.clear();
706
known_bad_files_.clear();
670
707
Symbol result = FindSymbol(name);
672
709
if (result.IsNull() && pool->underlay_ != NULL) {
877
void FileDescriptorTables::BuildLocationsByPath(
878
pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
879
for (int i = 0, len = p->second->location_size(); i < len; ++i) {
880
const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
881
p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
885
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
886
const vector<int>& path, const SourceCodeInfo* info) const {
887
pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
888
make_pair(this, info));
889
locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
890
return FindPtrOrNull(locations_by_path_, Join(path, ","));
840
893
// ===================================================================
841
894
// DescriptorPool
1306
bool Descriptor::IsExtensionNumber(int number) const {
1396
const Descriptor::ExtensionRange*
1397
Descriptor::FindExtensionRangeContainingNumber(int number) const {
1307
1398
// Linear search should be fine because we don't expect a message to have
1308
1399
// more than a couple extension ranges.
1309
1400
for (int i = 0; i < extension_range_count(); i++) {
1310
1401
if (number >= extension_range(i)->start &&
1311
1402
number < extension_range(i)->end) {
1403
return extension_range(i);
1318
1409
// -------------------------------------------------------------------
1357
1447
bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
1358
1448
if (fallback_database_ == NULL) return false;
1360
// We skip looking in the fallback database if the name is a sub-symbol of
1361
// any descriptor that already exists in the descriptor pool (except for
1362
// package descriptors). This is valid because all symbols except for
1363
// packages are defined in a single file, so if the symbol exists then we
1364
// should already have its definition.
1366
// The other reason to do this is to support "overriding" type definitions
1367
// by merging two databases that define the same type. (Yes, people do
1368
// this.) The main difficulty with making this work is that
1369
// FindFileContainingSymbol() is allowed to return both false positives
1370
// (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
1371
// negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). When two
1372
// such databases are merged, looking up a non-existent sub-symbol of a type
1373
// that already exists in the descriptor pool can result in an attempt to
1374
// load multiple definitions of the same type. The check below avoids this.
1375
if (IsSubSymbolOfBuiltType(name)) return false;
1450
if (tables_->known_bad_symbols_.count(name) > 0) return false;
1377
1452
FileDescriptorProto file_proto;
1378
if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) {
1382
if (tables_->FindFile(file_proto.name()) != NULL) {
1383
// We've already loaded this file, and it apparently doesn't contain the
1384
// symbol we're looking for. Some DescriptorDatabases return false
1389
if (BuildFileFromDatabase(file_proto) == NULL) {
1453
if (// We skip looking in the fallback database if the name is a sub-symbol
1454
// of any descriptor that already exists in the descriptor pool (except
1455
// for package descriptors). This is valid because all symbols except
1456
// for packages are defined in a single file, so if the symbol exists
1457
// then we should already have its definition.
1459
// The other reason to do this is to support "overriding" type
1460
// definitions by merging two databases that define the same type. (Yes,
1461
// people do this.) The main difficulty with making this work is that
1462
// FindFileContainingSymbol() is allowed to return both false positives
1463
// (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
1464
// negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
1465
// When two such databases are merged, looking up a non-existent
1466
// sub-symbol of a type that already exists in the descriptor pool can
1467
// result in an attempt to load multiple definitions of the same type.
1468
// The check below avoids this.
1469
IsSubSymbolOfBuiltType(name)
1471
// Look up file containing this symbol in fallback database.
1472
|| !fallback_database_->FindFileContainingSymbol(name, &file_proto)
1474
// Check if we've already built this file. If so, it apparently doesn't
1475
// contain the symbol we're looking for. Some DescriptorDatabases
1476
// return false positives.
1477
|| tables_->FindFile(file_proto.name()) != NULL
1480
|| BuildFileFromDatabase(file_proto) == NULL) {
1481
tables_->known_bad_symbols_.insert(name);
1681
1784
bool FormatBracketedOptions(int depth, const Message &options, string *output) {
1682
1785
vector<string> all_options;
1683
1786
if (RetrieveOptions(depth, options, &all_options)) {
1684
output->append(JoinStrings(all_options, ", "));
1787
output->append(Join(all_options, ", "));
1686
1789
return !all_options.empty();
1815
1918
enum_type(i)->DebugString(depth, contents);
1817
1920
for (int i = 0; i < field_count(); i++) {
1818
field(i)->DebugString(depth, contents);
1921
if (field(i)->containing_oneof() == NULL) {
1922
field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents);
1923
} else if (field(i)->containing_oneof()->field(0) == field(i)) {
1924
// This is the first field in this oneof, so print the whole oneof.
1925
field(i)->containing_oneof()->DebugString(depth, contents);
1821
1929
for (int i = 0; i < extension_range_count(); i++) {
1834
1942
strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n",
1835
1943
prefix, containing_type->full_name());
1837
extension(i)->DebugString(depth + 1, contents);
1945
extension(i)->DebugString(
1946
depth + 1, FieldDescriptor::PRINT_LABEL, contents);
1839
1948
if (extension_count() > 0)
1840
1949
strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
1850
1959
containing_type()->full_name());
1853
DebugString(depth, &contents);
1962
DebugString(depth, PRINT_LABEL, &contents);
1854
1963
if (is_extension()) {
1855
contents.append("}\n");
1964
contents.append("}\n");
1857
1966
return contents;
1860
void FieldDescriptor::DebugString(int depth, string *contents) const {
1969
void FieldDescriptor::DebugString(int depth,
1970
PrintLabelFlag print_label_flag,
1971
string *contents) const {
1861
1972
string prefix(depth * 2, ' ');
1862
1973
string field_type;
1863
1974
switch (type()) {
2024
string OneofDescriptor::DebugString() const {
2026
DebugString(0, &contents);
2030
void OneofDescriptor::DebugString(int depth, string* contents) const {
2031
string prefix(depth * 2, ' ');
2033
strings::SubstituteAndAppend(
2034
contents, "$0 oneof $1 {\n", prefix, name());
2035
for (int i = 0; i < field_count(); i++) {
2036
field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents);
2038
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
1907
2041
string EnumDescriptor::DebugString() const {
1908
2042
string contents;
1909
2043
DebugString(0, &contents);
1987
2121
// Location methods ===============================================
1989
static bool PathsEqual(const vector<int>& x, const RepeatedField<int32>& y) {
1990
if (x.size() != y.size()) return false;
1991
for (int i = 0; i < x.size(); ++i) {
1992
if (x[i] != y.Get(i)) return false;
1997
2123
bool FileDescriptor::GetSourceLocation(const vector<int>& path,
1998
2124
SourceLocation* out_location) const {
1999
2125
GOOGLE_CHECK_NOTNULL(out_location);
2000
const SourceCodeInfo* info = source_code_info_;
2001
for (int i = 0; info && i < info->location_size(); ++i) {
2002
if (PathsEqual(path, info->location(i).path())) {
2003
const RepeatedField<int32>& span = info->location(i).span();
2126
if (source_code_info_) {
2127
if (const SourceCodeInfo_Location* loc =
2128
tables_->GetSourceLocation(path, source_code_info_)) {
2129
const RepeatedField<int32>& span = loc->span();
2004
2130
if (span.size() == 3 || span.size() == 4) {
2005
2131
out_location->start_line = span.Get(0);
2006
2132
out_location->start_column = span.Get(1);
2007
2133
out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
2008
2134
out_location->end_column = span.Get(span.size() - 1);
2010
out_location->leading_comments = info->location(i).leading_comments();
2011
out_location->trailing_comments = info->location(i).trailing_comments();
2136
out_location->leading_comments = loc->leading_comments();
2137
out_location->trailing_comments = loc->trailing_comments();
2071
2203
void FieldDescriptor::GetLocationPath(vector<int>* output) const {
2204
if (is_extension()) {
2205
if (extension_scope() == NULL) {
2206
output->push_back(FileDescriptorProto::kExtensionFieldNumber);
2207
output->push_back(index());
2209
extension_scope()->GetLocationPath(output);
2210
output->push_back(DescriptorProto::kExtensionFieldNumber);
2211
output->push_back(index());
2214
containing_type()->GetLocationPath(output);
2215
output->push_back(DescriptorProto::kFieldFieldNumber);
2216
output->push_back(index());
2220
void OneofDescriptor::GetLocationPath(vector<int>* output) const {
2072
2221
containing_type()->GetLocationPath(output);
2073
output->push_back(DescriptorProto::kFieldFieldNumber);
2222
output->push_back(DescriptorProto::kOneofDeclFieldNumber);
2074
2223
output->push_back(index());
2156
2305
FileDescriptorTables* file_tables_;
2157
2306
set<const FileDescriptor*> dependencies_;
2308
// unused_dependency_ is used to record the unused imported files.
2309
// Note: public import is not considered.
2310
set<const FileDescriptor*> unused_dependency_;
2159
2312
// If LookupSymbol() finds a symbol that is in a file which is not a declared
2160
2313
// dependency of this file, it will fail, but will set
2161
2314
// possible_undeclared_dependency_ to point at that file. This is only used
2166
2319
const FileDescriptor* possible_undeclared_dependency_;
2167
2320
string possible_undeclared_dependency_name_;
2322
// If LookupSymbol() could resolve a symbol which is not defined,
2323
// record the resolved name. This is only used by AddNotDefinedError()
2324
// to report a more useful error message.
2325
string undefine_resolved_name_;
2169
2327
void AddError(const string& element_name,
2170
2328
const Message& descriptor,
2171
2329
DescriptorPool::ErrorCollector::ErrorLocation location,
2172
2330
const string& error);
2331
void AddError(const string& element_name,
2332
const Message& descriptor,
2333
DescriptorPool::ErrorCollector::ErrorLocation location,
2335
void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
2336
void AddTwiceListedError(const FileDescriptorProto& proto, int index);
2337
void AddImportError(const FileDescriptorProto& proto, int index);
2174
2339
// Adds an error indicating that undefined_symbol was not defined. Must
2175
2340
// only be called after LookupSymbol() fails.
2179
2344
DescriptorPool::ErrorCollector::ErrorLocation location,
2180
2345
const string& undefined_symbol);
2347
void AddWarning(const string& element_name, const Message& descriptor,
2348
DescriptorPool::ErrorCollector::ErrorLocation location,
2349
const string& error);
2182
2351
// Silly helper which determines if the given file is in the given package.
2183
2352
// I.e., either file->package() == package_name or file->package() is a
2184
2353
// nested package within package_name.
2313
2482
void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
2314
2483
const Descriptor* parent,
2315
2484
Descriptor::ExtensionRange* result);
2485
void BuildOneof(const OneofDescriptorProto& proto,
2487
OneofDescriptor* result);
2316
2488
void BuildEnum(const EnumDescriptorProto& proto,
2317
2489
const Descriptor* parent,
2318
2490
EnumDescriptor* result);
2521
2702
const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
2522
2703
const FileDescriptorProto& proto) const {
2523
2704
mutex_->AssertHeld();
2524
return DescriptorBuilder(this, tables_.get(),
2525
default_error_collector_).BuildFile(proto);
2705
if (tables_->known_bad_files_.count(proto.name()) > 0) {
2708
const FileDescriptor* result =
2709
DescriptorBuilder(this, tables_.get(),
2710
default_error_collector_).BuildFile(proto);
2711
if (result == NULL) {
2712
tables_->known_bad_files_.insert(proto.name());
2528
2717
DescriptorBuilder::DescriptorBuilder(
2555
2745
had_errors_ = true;
2748
void DescriptorBuilder::AddError(
2749
const string& element_name,
2750
const Message& descriptor,
2751
DescriptorPool::ErrorCollector::ErrorLocation location,
2752
const char* error) {
2753
AddError(element_name, descriptor, location, string(error));
2558
2756
void DescriptorBuilder::AddNotDefinedError(
2559
2757
const string& element_name,
2560
2758
const Message& descriptor,
2561
2759
DescriptorPool::ErrorCollector::ErrorLocation location,
2562
2760
const string& undefined_symbol) {
2563
if (possible_undeclared_dependency_ == NULL) {
2761
if (possible_undeclared_dependency_ == NULL &&
2762
undefine_resolved_name_.empty()) {
2564
2763
AddError(element_name, descriptor, location,
2565
2764
"\"" + undefined_symbol + "\" is not defined.");
2567
AddError(element_name, descriptor, location,
2568
"\"" + possible_undeclared_dependency_name_ +
2569
"\" seems to be defined in \"" +
2570
possible_undeclared_dependency_->name() + "\", which is not "
2571
"imported by \"" + filename_ + "\". To use it here, please "
2572
"add the necessary import.");
2766
if (possible_undeclared_dependency_ != NULL) {
2767
AddError(element_name, descriptor, location,
2768
"\"" + possible_undeclared_dependency_name_ +
2769
"\" seems to be defined in \"" +
2770
possible_undeclared_dependency_->name() + "\", which is not "
2771
"imported by \"" + filename_ + "\". To use it here, please "
2772
"add the necessary import.");
2774
if (!undefine_resolved_name_.empty()) {
2775
AddError(element_name, descriptor, location,
2776
"\"" + undefined_symbol + "\" is resolved to \"" +
2777
undefine_resolved_name_ + "\", which is not defined. "
2778
"The innermost scope is searched first in name resolution. "
2779
"Consider using a leading '.'(i.e., \"."
2780
+ undefined_symbol +
2781
"\") to start from the outermost scope.");
2786
void DescriptorBuilder::AddWarning(
2787
const string& element_name, const Message& descriptor,
2788
DescriptorPool::ErrorCollector::ErrorLocation location,
2789
const string& error) {
2790
if (error_collector_ == NULL) {
2791
GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
2793
error_collector_->AddWarning(filename_, element_name, &descriptor, location,
2843
3074
memset(placeholder, 0, sizeof(*placeholder));
2845
3076
placeholder->name_ = tables_->AllocateString(name);
2846
placeholder->package_ = &kEmptyString;
3077
placeholder->package_ = &internal::GetEmptyString();
2847
3078
placeholder->pool_ = pool_;
2848
3079
placeholder->options_ = &FileOptions::default_instance();
2849
3080
placeholder->tables_ = &FileDescriptorTables::kEmpty;
3081
placeholder->is_placeholder_ = true;
2850
3082
// All other fields are zero or NULL.
2852
3084
return placeholder;
3017
3249
METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \
3252
void DescriptorBuilder::AddRecursiveImportError(
3253
const FileDescriptorProto& proto, int from_here) {
3254
string error_message("File recursively imports itself: ");
3255
for (int i = from_here; i < tables_->pending_files_.size(); i++) {
3256
error_message.append(tables_->pending_files_[i]);
3257
error_message.append(" -> ");
3259
error_message.append(proto.name());
3261
AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
3265
void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
3267
AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
3268
"Import \"" + proto.dependency(index) + "\" was listed twice.");
3271
void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
3274
if (pool_->fallback_database_ == NULL) {
3275
message = "Import \"" + proto.dependency(index) +
3276
"\" has not been loaded.";
3278
message = "Import \"" + proto.dependency(index) +
3279
"\" was not found or had errors.";
3281
AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message);
3284
static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
3285
const FileDescriptorProto& proto) {
3286
FileDescriptorProto existing_proto;
3287
existing_file->CopyTo(&existing_proto);
3288
return existing_proto.SerializeAsString() == proto.SerializeAsString();
3020
3291
const FileDescriptor* DescriptorBuilder::BuildFile(
3021
3292
const FileDescriptorProto& proto) {
3022
3293
filename_ = proto.name();
3029
3300
const FileDescriptor* existing_file = tables_->FindFile(filename_);
3030
3301
if (existing_file != NULL) {
3031
3302
// File already in pool. Compare the existing one to the input.
3032
FileDescriptorProto existing_proto;
3033
existing_file->CopyTo(&existing_proto);
3034
if (existing_proto.SerializeAsString() == proto.SerializeAsString()) {
3303
if (ExistingFileMatchesProto(existing_file, proto)) {
3035
3304
// They're identical. Return the existing descriptor.
3036
3305
return existing_file;
3051
3320
for (int i = 0; i < tables_->pending_files_.size(); i++) {
3052
3321
if (tables_->pending_files_[i] == proto.name()) {
3053
string error_message("File recursively imports itself: ");
3054
for (; i < tables_->pending_files_.size(); i++) {
3055
error_message.append(tables_->pending_files_[i]);
3056
error_message.append(" -> ");
3058
error_message.append(proto.name());
3060
AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
3322
AddRecursiveImportError(proto, i);
3131
3393
result->dependency_count_ = proto.dependency_size();
3132
3394
result->dependencies_ =
3133
3395
tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
3396
unused_dependency_.clear();
3398
for (int i = 0; i < proto.weak_dependency_size(); ++i) {
3399
weak_deps.insert(proto.weak_dependency(i));
3134
3401
for (int i = 0; i < proto.dependency_size(); i++) {
3135
3402
if (!seen_dependencies.insert(proto.dependency(i)).second) {
3136
AddError(proto.name(), proto,
3137
DescriptorPool::ErrorCollector::OTHER,
3138
"Import \"" + proto.dependency(i) + "\" was listed twice.");
3403
AddTwiceListedError(proto, i);
3141
3406
const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
3146
3411
if (dependency == NULL) {
3147
if (pool_->allow_unknown_) {
3412
if (pool_->allow_unknown_ ||
3413
(!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
3148
3414
dependency = NewPlaceholderFile(proto.dependency(i));
3151
if (pool_->fallback_database_ == NULL) {
3152
message = "Import \"" + proto.dependency(i) +
3153
"\" has not been loaded.";
3155
message = "Import \"" + proto.dependency(i) +
3156
"\" was not found or had errors.";
3158
AddError(proto.name(), proto,
3159
DescriptorPool::ErrorCollector::OTHER,
3416
AddImportError(proto, i);
3419
// Add to unused_dependency_ to track unused imported files.
3420
// Note: do not track unused imported files for public import.
3421
if (pool_->enforce_dependencies_ &&
3422
(pool_->unused_import_track_files_.find(proto.name()) !=
3423
pool_->unused_import_track_files_.end()) &&
3424
(dependency->public_dependency_count() == 0)) {
3425
unused_dependency_.insert(dependency);
3266
3538
result->is_placeholder_ = false;
3267
3539
result->is_unqualified_placeholder_ = false;
3541
// Build oneofs first so that fields and extension ranges can refer to them.
3542
BUILD_ARRAY(proto, result, oneof_decl , BuildOneof , result);
3269
3543
BUILD_ARRAY(proto, result, field , BuildField , result);
3270
3544
BUILD_ARRAY(proto, result, nested_type , BuildMessage , result);
3271
3545
BUILD_ARRAY(proto, result, enum_type , BuildEnum , result);
3356
3630
result->label_ = static_cast<FieldDescriptor::Label>(
3357
3631
implicit_cast<int>(proto.label()));
3633
// An extension cannot have a required field (b/13365836).
3634
if (result->is_extension_ &&
3635
result->label_ == FieldDescriptor::LABEL_REQUIRED) {
3636
AddError(result->full_name(), proto,
3637
// Error location `TYPE`: we would really like to indicate
3638
// `LABEL`, but the `ErrorLocation` enum has no entry for this, and
3639
// we don't necessarily know about all implementations of the
3640
// `ErrorCollector` interface to extend them to handle the new
3641
// error location type properly.
3642
DescriptorPool::ErrorCollector::TYPE,
3643
"Message extensions cannot have required fields.");
3359
3646
// Some of these may be filled in when cross-linking.
3360
3647
result->containing_type_ = NULL;
3361
3648
result->extension_scope_ = NULL;
3528
3816
result->extension_scope_ = parent;
3818
if (proto.has_oneof_index()) {
3819
AddError(result->full_name(), proto,
3820
DescriptorPool::ErrorCollector::OTHER,
3821
"FieldDescriptorProto.oneof_index should not be set for "
3825
// Fill in later (maybe).
3826
result->containing_oneof_ = NULL;
3530
3828
if (proto.has_extendee()) {
3531
3829
AddError(result->full_name(), proto,
3536
3834
result->containing_type_ = parent;
3836
if (proto.has_oneof_index()) {
3837
if (proto.oneof_index() < 0 ||
3838
proto.oneof_index() >= parent->oneof_decl_count()) {
3839
AddError(result->full_name(), proto,
3840
DescriptorPool::ErrorCollector::OTHER,
3841
strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
3842
"out of range for type \"$1\".",
3843
proto.oneof_index(),
3845
result->containing_oneof_ = NULL;
3847
result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
3850
result->containing_oneof_ = NULL;
3539
3854
// Copy options.
3889
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
3891
OneofDescriptor* result) {
3892
string* full_name = tables_->AllocateString(parent->full_name());
3893
full_name->append(1, '.');
3894
full_name->append(proto.name());
3896
ValidateSymbolName(proto.name(), *full_name, proto);
3898
result->name_ = tables_->AllocateString(proto.name());
3899
result->full_name_ = full_name;
3901
result->containing_type_ = parent;
3903
// We need to fill these in later.
3904
result->field_count_ = 0;
3905
result->fields_ = NULL;
3907
AddSymbol(result->full_name(), parent, result->name(),
3908
proto, Symbol(result));
3574
3911
void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
3575
3912
const Descriptor* parent,
3576
3913
EnumDescriptor* result) {
3780
4117
for (int i = 0; i < message->extension_count(); i++) {
3781
4118
CrossLinkField(&message->extensions_[i], proto.extension(i));
4121
// Set up field array for each oneof.
4123
// First count the number of fields per oneof.
4124
for (int i = 0; i < message->field_count(); i++) {
4125
const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
4126
if (oneof_decl != NULL) {
4127
// Must go through oneof_decls_ array to get a non-const version of the
4129
++message->oneof_decls_[oneof_decl->index()].field_count_;
4133
// Then allocate the arrays.
4134
for (int i = 0; i < message->oneof_decl_count(); i++) {
4135
OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
4137
if (oneof_decl->field_count() == 0) {
4138
AddError(message->full_name() + "." + oneof_decl->name(),
4139
proto.oneof_decl(i),
4140
DescriptorPool::ErrorCollector::NAME,
4141
"Oneof must have at least one field.");
4144
oneof_decl->fields_ =
4145
tables_->AllocateArray<const FieldDescriptor*>(oneof_decl->field_count_);
4146
oneof_decl->field_count_ = 0;
4149
// Then fill them in.
4150
for (int i = 0; i < message->field_count(); i++) {
4151
const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
4152
if (oneof_decl != NULL) {
4153
OneofDescriptor* mutable_oneof_decl =
4154
&message->oneof_decls_[oneof_decl->index()];
4155
message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
4156
mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] =
3785
4162
void DescriptorBuilder::CrossLinkField(
3805
4182
field->containing_type_ = extendee.descriptor;
3807
if (!field->containing_type()->IsExtensionNumber(field->number())) {
4184
const Descriptor::ExtensionRange* extension_range = field->containing_type()
4185
->FindExtensionRangeContainingNumber(field->number());
4187
if (extension_range == NULL) {
3808
4188
AddError(field->full_name(), proto,
3809
4189
DescriptorPool::ErrorCollector::NUMBER,
3810
4190
strings::Substitute("\"$0\" does not declare $1 as an "
4197
if (field->containing_oneof() != NULL) {
4198
if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
4199
// Note that this error will never happen when parsing .proto files.
4200
// It can only happen if you manually construct a FileDescriptorProto
4201
// that is incorrect.
4202
AddError(field->full_name(), proto,
4203
DescriptorPool::ErrorCollector::NAME,
4204
"Fields of oneofs must themselves have label LABEL_OPTIONAL.");
3817
4208
if (proto.has_type_name()) {
3818
4209
// Assume we are expecting a message type unless the proto contains some
3819
4210
// evidence that it expects an enum type. This only makes a difference if
3826
4217
expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE,
4220
// If the type is a weak type, we change the type to a google.protobuf.Empty field.
4221
if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) {
4222
type = FindSymbol(kNonLinkedWeakMessageReplacementName);
3829
4225
if (type.IsNull()) {
3830
4226
AddNotDefinedError(field->full_name(), proto,
3831
4227
DescriptorPool::ErrorCollector::TYPE,
3879
4275
if (field->has_default_value()) {
3880
// We can't just use field->enum_type()->FindValueByName() here
3881
// because that locks the pool's mutex, which we have already locked
3883
Symbol default_value =
3884
LookupSymbolNoPlaceholder(proto.default_value(),
3885
field->enum_type()->full_name());
3887
if (default_value.type == Symbol::ENUM_VALUE &&
3888
default_value.enum_value_descriptor->type() == field->enum_type()) {
3889
field->default_value_enum_ = default_value.enum_value_descriptor;
4276
// Ensure that the default value is an identifier. Parser cannot always
4277
// verify this because it does not have complete type information.
4278
// N.B. that this check yields better error messages but is not
4279
// necessary for correctness (an enum symbol must be a valid identifier
4280
// anyway), only for better errors.
4281
if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
3891
4282
AddError(field->full_name(), proto,
3892
4283
DescriptorPool::ErrorCollector::DEFAULT_VALUE,
3893
"Enum type \"" + field->enum_type()->full_name() +
3894
"\" has no value named \"" + proto.default_value() + "\".");
4284
"Default value for an enum field must be an identifier.");
4286
// We can't just use field->enum_type()->FindValueByName() here
4287
// because that locks the pool's mutex, which we have already locked
4289
Symbol default_value =
4290
LookupSymbolNoPlaceholder(proto.default_value(),
4291
field->enum_type()->full_name());
4293
if (default_value.type == Symbol::ENUM_VALUE &&
4294
default_value.enum_value_descriptor->type() ==
4295
field->enum_type()) {
4296
field->default_value_enum_ = default_value.enum_value_descriptor;
4298
AddError(field->full_name(), proto,
4299
DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4300
"Enum type \"" + field->enum_type()->full_name() +
4301
"\" has no value named \"" + proto.default_value() +
3896
4305
} else if (field->enum_type()->value_count() > 0) {
3897
4306
// All enums must have at least one value, or we would have reported
3935
4344
field->containing_type()->full_name(),
3936
4345
conflicting_field->name()));
3940
if (field->is_extension()) {
3941
// No need for error checking: if the extension number collided,
3942
// we've already been informed of it by the if() above.
3943
tables_->AddExtension(field);
4348
if (field->is_extension()) {
4349
if (!tables_->AddExtension(field)) {
4350
const FieldDescriptor* conflicting_field =
4351
tables_->FindExtension(field->containing_type(), field->number());
4352
string error_msg = strings::Substitute(
4353
"Extension number $0 has already been used in \"$1\" by extension "
4354
"\"$2\" defined in $3.",
4356
field->containing_type()->full_name(),
4357
conflicting_field->full_name(),
4358
conflicting_field->file()->name());
4359
// Conflicting extension numbers should be an error. However, before
4360
// turning this into an error we need to fix all existing broken
4362
// TODO(xiaofeng): Change this to an error.
4363
AddWarning(field->full_name(), proto,
4364
DescriptorPool::ErrorCollector::NUMBER, error_msg);
3946
4369
// Add the field to the lowercase-name and camelcase-name tables.
4388
4813
// so we will just leave it as uninterpreted.
4389
4814
AddWithoutInterpreting(*uninterpreted_option_, options);
4816
} else if (!(builder_->undefine_resolved_name_).empty()) {
4817
// Option is resolved to a name which is not defined.
4818
return AddNameError(
4819
"Option \"" + debug_msg_name + "\" is resolved to \"(" +
4820
builder_->undefine_resolved_name_ +
4821
")\", which is not defined. The innermost scope is searched first "
4822
"in name resolution. Consider using a leading '.'(i.e., \"(." +
4823
debug_msg_name.substr(1) +
4824
"\") to start from the outermost scope.");
4392
4826
return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
4408
4842
"\" is not a field or extension of message \"" +
4409
4843
descriptor->name() + "\".");
4411
} else if (field->is_repeated()) {
4412
return AddNameError("Option field \"" + debug_msg_name +
4413
"\" is repeated. Repeated options are not "
4415
4845
} else if (i < uninterpreted_option_->name_size() - 1) {
4416
4846
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
4417
4847
return AddNameError("Option \"" + debug_msg_name +
4418
4848
"\" is an atomic type, not a message.");
4849
} else if (field->is_repeated()) {
4850
return AddNameError("Option field \"" + debug_msg_name +
4851
"\" is a repeated message. Repeated message "
4852
"options must be initialized using an "
4853
"aggregate value.");
4420
4855
// Drill down into the submessage.
4421
4856
intermediate_fields.push_back(field);
4810
virtual void AddError(int line, int column, const string& message) {
5245
virtual void AddError(int /* line */, int /* column */,
5246
const string& message) {
4811
5247
if (!error_.empty()) {
4812
5248
error_ += "; ";
4814
5250
error_ += message;
4817
virtual void AddWarning(int line, int column, const string& message) {
5253
virtual void AddWarning(int /* line */, int /* column */,
5254
const string& /* message */) {
4818
5255
// Ignore warnings
5385
void DescriptorBuilder::LogUnusedDependency(const FileDescriptor* result) {
5387
if (!unused_dependency_.empty()) {
5388
std::set<string> annotation_extensions;
5389
annotation_extensions.insert("google.protobuf.MessageOptions");
5390
annotation_extensions.insert("google.protobuf.FileOptions");
5391
annotation_extensions.insert("google.protobuf.FieldOptions");
5392
annotation_extensions.insert("google.protobuf.EnumOptions");
5393
annotation_extensions.insert("google.protobuf.EnumValueOptions");
5394
annotation_extensions.insert("google.protobuf.ServiceOptions");
5395
annotation_extensions.insert("google.protobuf.MethodOptions");
5396
annotation_extensions.insert("google.protobuf.StreamOptions");
5397
for (set<const FileDescriptor*>::const_iterator
5398
it = unused_dependency_.begin();
5399
it != unused_dependency_.end(); ++it) {
5400
// Do not log warnings for proto files which extend annotations.
5402
for (i = 0 ; i < (*it)->extension_count(); ++i) {
5403
if (annotation_extensions.find(
5404
(*it)->extension(i)->containing_type()->full_name())
5405
!= annotation_extensions.end()) {
5409
// Log warnings for unused imported files.
5410
if (i == (*it)->extension_count()) {
5411
GOOGLE_LOG(WARNING) << "Warning: Unused import: \"" << result->name()
5412
<< "\" imports \"" << (*it)->name()
5413
<< "\" which is not used.";
4948
5419
} // namespace protobuf
4949
5420
} // namespace google