~ubuntu-branches/debian/stretch/protobuf/stretch

« back to all changes in this revision

Viewing changes to src/google/protobuf/descriptor.cc

  • Committer: Package Import Robot
  • Author(s): Robert S. Edmonds
  • Date: 2014-09-11 22:50:10 UTC
  • mfrom: (10.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20140911225010-wt4yo9dpc1fzuq5g
Tags: 2.6.0-3
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <google/protobuf/stubs/hash.h>
36
36
#include <map>
37
37
#include <set>
 
38
#include <string>
38
39
#include <vector>
39
40
#include <algorithm>
40
41
#include <limits>
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>
53
56
#include <google/protobuf/stubs/once.h>
54
57
#include <google/protobuf/stubs/strutil.h>
55
58
#include <google/protobuf/stubs/substitute.h>
56
 
#include <google/protobuf/stubs/map-util.h>
 
59
#include <google/protobuf/stubs/map_util.h>
57
60
#include <google/protobuf/stubs/stl_util.h>
58
61
 
59
62
#undef PACKAGE  // autoheader #defines this.  :(
131
134
  "repeated",  // LABEL_REPEATED
132
135
};
133
136
 
 
137
static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
 
138
 
134
139
#ifndef _MSC_VER  // MSVC doesn't need these and won't even accept them.
135
140
const int FieldDescriptor::kMaxNumber;
136
141
const int FieldDescriptor::kFirstReservedNumber;
139
144
 
140
145
namespace {
141
146
 
142
 
const string kEmptyString;
143
 
 
144
147
string ToCamelCase(const string& input) {
145
148
  bool capitalize_next = false;
146
149
  string result;
201
204
    return reinterpret_cast<intptr_t>(p.first) * ((1 << 16) - 1) + p.second;
202
205
  }
203
206
 
 
207
#ifdef _MSC_VER
204
208
  // Used only by MSVC and platforms where hash_map is not available.
205
209
  static const size_t bucket_size = 4;
206
210
  static const size_t min_buckets = 8;
 
211
#endif
207
212
  inline bool operator()(const PairType& a, const PairType& b) const {
208
213
    return a.first < b.first ||
209
214
          (a.first == b.first && a.second < b.second);
222
227
           cstring_hash(p.second);
223
228
  }
224
229
 
 
230
#ifdef _MSC_VER
225
231
  // Used only by MSVC and platforms where hash_map is not available.
226
232
  static const size_t bucket_size = 4;
227
233
  static const size_t min_buckets = 8;
 
234
#endif
228
235
  inline bool operator()(const PointerStringPair& a,
229
236
                         const PointerStringPair& b) const {
230
237
    if (a.first < b.first) return true;
236
243
 
237
244
struct Symbol {
238
245
  enum Type {
239
 
    NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
 
246
    NULL_SYMBOL, MESSAGE, FIELD, ONEOF, ENUM, ENUM_VALUE, SERVICE, METHOD,
240
247
    PACKAGE
241
248
  };
242
249
  Type type;
243
250
  union {
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;
268
276
 
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     )
280
289
      case NULL_SYMBOL: return NULL;
281
290
      case MESSAGE    : return descriptor           ->file();
282
291
      case FIELD      : return field_descriptor     ->file();
 
292
      case ONEOF      : return oneof_descriptor     ->containing_type()->file();
283
293
      case ENUM       : return enum_descriptor      ->file();
284
294
      case ENUM_VALUE : return enum_value_descriptor->type()->file();
285
295
      case SERVICE    : return service_descriptor   ->file();
316
326
// for that.
317
327
typedef map<DescriptorIntPair, const FieldDescriptor*>
318
328
  ExtensionsGroupedByDescriptorMap;
319
 
 
 
329
typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
320
330
}  // anonymous namespace
321
331
 
322
332
// ===================================================================
370
380
  vector<string> pending_files_;
371
381
 
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_;
376
388
 
 
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_;
 
394
 
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_;
390
408
  // declaring Symbol in descriptor.h, which would drag all kinds of other
391
409
  // stuff into the header.  Yay C++.
392
410
  Symbol FindByNameHelper(
393
 
    const DescriptorPool* pool, const string& name) const;
 
411
    const DescriptorPool* pool, const string& name);
394
412
 
395
413
  // These return NULL if not found.
396
414
  inline const FileDescriptor* FindFile(const string& key) const;
531
549
  // fails because we allow duplicates; the first field by the name wins.
532
550
  void AddFieldByStylizedNames(const FieldDescriptor* field);
533
551
 
 
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);
 
556
 
 
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;
 
563
 
534
564
 private:
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_;
 
570
 
 
571
  // Populated on first request to save space, hence constness games.
 
572
  mutable GoogleOnceDynamic locations_by_path_once_;
 
573
  mutable LocationsByPathMap locations_by_path_;
540
574
};
541
575
 
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) {}
665
700
}
666
701
 
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);
671
708
 
672
709
  if (result.IsNull() && pool->underlay_ != NULL) {
813
850
}
814
851
 
815
852
template<typename Type>
816
 
Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) {
 
853
Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) {
817
854
  Type* result = new Type;
818
855
  messages_.push_back(result);
819
856
  return result;
837
874
  return result;
838
875
}
839
876
 
 
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;
 
882
  }
 
883
}
 
884
 
 
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, ","));
 
891
}
 
892
 
840
893
// ===================================================================
841
894
// DescriptorPool
842
895
 
849
902
    underlay_(NULL),
850
903
    tables_(new Tables),
851
904
    enforce_dependencies_(true),
852
 
    allow_unknown_(false) {}
 
905
    allow_unknown_(false),
 
906
    enforce_weak_(false) {}
853
907
 
854
908
DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
855
909
                               ErrorCollector* error_collector)
859
913
    underlay_(NULL),
860
914
    tables_(new Tables),
861
915
    enforce_dependencies_(true),
862
 
    allow_unknown_(false) {
 
916
    allow_unknown_(false),
 
917
    enforce_weak_(false) {
863
918
}
864
919
 
865
920
DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
869
924
    underlay_(underlay),
870
925
    tables_(new Tables),
871
926
    enforce_dependencies_(true),
872
 
    allow_unknown_(false) {}
 
927
    allow_unknown_(false),
 
928
    enforce_weak_(false) {}
873
929
 
874
930
DescriptorPool::~DescriptorPool() {
875
931
  if (mutex_ != NULL) delete mutex_;
882
938
  enforce_dependencies_ = false;
883
939
}
884
940
 
 
941
void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) {
 
942
  unused_import_track_files_.insert(file_name);
 
943
}
 
944
 
 
945
void DescriptorPool::ClearUnusedImportTrackFiles() {
 
946
  unused_import_track_files_.clear();
 
947
}
 
948
 
885
949
bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
886
950
  MutexLockMaybe lock(mutex_);
887
951
  return tables_->FindFile(filename) != NULL;
963
1027
 
964
1028
const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
965
1029
  MutexLockMaybe lock(mutex_);
 
1030
  tables_->known_bad_symbols_.clear();
 
1031
  tables_->known_bad_files_.clear();
966
1032
  const FileDescriptor* result = tables_->FindFile(name);
967
1033
  if (result != NULL) return result;
968
1034
  if (underlay_ != NULL) {
979
1045
const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
980
1046
    const string& symbol_name) const {
981
1047
  MutexLockMaybe lock(mutex_);
 
1048
  tables_->known_bad_symbols_.clear();
 
1049
  tables_->known_bad_files_.clear();
982
1050
  Symbol result = tables_->FindSymbol(symbol_name);
983
1051
  if (!result.IsNull()) return result.GetFile();
984
1052
  if (underlay_ != NULL) {
1021
1089
  }
1022
1090
}
1023
1091
 
 
1092
const OneofDescriptor* DescriptorPool::FindOneofByName(
 
1093
    const string& name) const {
 
1094
  Symbol result = tables_->FindByNameHelper(this, name);
 
1095
  return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL;
 
1096
}
 
1097
 
1024
1098
const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
1025
1099
    const string& name) const {
1026
1100
  Symbol result = tables_->FindByNameHelper(this, name);
1049
1123
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
1050
1124
    const Descriptor* extendee, int number) const {
1051
1125
  MutexLockMaybe lock(mutex_);
 
1126
  tables_->known_bad_symbols_.clear();
 
1127
  tables_->known_bad_files_.clear();
1052
1128
  const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1053
1129
  if (result != NULL) {
1054
1130
    return result;
1069
1145
void DescriptorPool::FindAllExtensions(
1070
1146
    const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
1071
1147
  MutexLockMaybe lock(mutex_);
 
1148
  tables_->known_bad_symbols_.clear();
 
1149
  tables_->known_bad_files_.clear();
1072
1150
 
1073
1151
  // Initialize tables_->extensions_ from the fallback database first
1074
1152
  // (but do this only once per descriptor).
1093
1171
  }
1094
1172
}
1095
1173
 
 
1174
 
1096
1175
// -------------------------------------------------------------------
1097
1176
 
1098
1177
const FieldDescriptor*
1139
1218
  }
1140
1219
}
1141
1220
 
 
1221
const OneofDescriptor*
 
1222
Descriptor::FindOneofByName(const string& key) const {
 
1223
  Symbol result =
 
1224
    file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
 
1225
  if (!result.IsNull()) {
 
1226
    return result.oneof_descriptor;
 
1227
  } else {
 
1228
    return NULL;
 
1229
  }
 
1230
}
 
1231
 
1142
1232
const FieldDescriptor*
1143
1233
Descriptor::FindExtensionByName(const string& key) const {
1144
1234
  Symbol result =
1303
1393
  }
1304
1394
}
1305
1395
 
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) {
1312
 
      return true;
 
1403
      return extension_range(i);
1313
1404
    }
1314
1405
  }
1315
 
  return false;
 
1406
  return NULL;
1316
1407
}
1317
1408
 
1318
1409
// -------------------------------------------------------------------
1328
1419
    tables_->known_bad_files_.insert(name);
1329
1420
    return false;
1330
1421
  }
1331
 
 
1332
1422
  return true;
1333
1423
}
1334
1424
 
1357
1447
bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
1358
1448
  if (fallback_database_ == NULL) return false;
1359
1449
 
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.
1365
 
  //
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;
1376
1451
 
1377
1452
  FileDescriptorProto file_proto;
1378
 
  if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) {
1379
 
    return false;
1380
 
  }
1381
 
 
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
1385
 
    // positives.
1386
 
    return false;
1387
 
  }
1388
 
 
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.
 
1458
      //
 
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)
 
1470
 
 
1471
      // Look up file containing this symbol in fallback database.
 
1472
      || !fallback_database_->FindFileContainingSymbol(name, &file_proto)
 
1473
 
 
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
 
1478
 
 
1479
      // Build the file.
 
1480
      || BuildFileFromDatabase(file_proto) == NULL) {
 
1481
    tables_->known_bad_symbols_.insert(name);
1390
1482
    return false;
1391
1483
  }
1392
1484
 
1513
1605
  for (int i = 0; i < field_count(); i++) {
1514
1606
    field(i)->CopyTo(proto->add_field());
1515
1607
  }
 
1608
  for (int i = 0; i < oneof_decl_count(); i++) {
 
1609
    oneof_decl(i)->CopyTo(proto->add_oneof_decl());
 
1610
  }
1516
1611
  for (int i = 0; i < nested_type_count(); i++) {
1517
1612
    nested_type(i)->CopyTo(proto->add_nested_type());
1518
1613
  }
1573
1668
    proto->set_default_value(DefaultValueAsString(false));
1574
1669
  }
1575
1670
 
 
1671
  if (containing_oneof() != NULL && !is_extension()) {
 
1672
    proto->set_oneof_index(containing_oneof()->index());
 
1673
  }
 
1674
 
1576
1675
  if (&options() != &FieldOptions::default_instance()) {
1577
1676
    proto->mutable_options()->CopyFrom(options());
1578
1677
  }
1579
1678
}
1580
1679
 
 
1680
void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
 
1681
  proto->set_name(name());
 
1682
}
 
1683
 
1581
1684
void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
1582
1685
  proto->set_name(name());
1583
1686
 
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, ", "));
1685
1788
  }
1686
1789
  return !all_options.empty();
1687
1790
}
1768
1871
      strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
1769
1872
                                   containing_type->full_name());
1770
1873
    }
1771
 
    extension(i)->DebugString(1, &contents);
 
1874
    extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents);
1772
1875
  }
1773
1876
  if (extension_count() > 0) contents.append("}\n\n");
1774
1877
 
1815
1918
    enum_type(i)->DebugString(depth, contents);
1816
1919
  }
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);
 
1926
    }
1819
1927
  }
1820
1928
 
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());
1836
1944
    }
1837
 
    extension(i)->DebugString(depth + 1, contents);
 
1945
    extension(i)->DebugString(
 
1946
        depth + 1, FieldDescriptor::PRINT_LABEL, contents);
1838
1947
  }
1839
1948
  if (extension_count() > 0)
1840
1949
    strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
1850
1959
                                 containing_type()->full_name());
1851
1960
    depth = 1;
1852
1961
  }
1853
 
  DebugString(depth, &contents);
 
1962
  DebugString(depth, PRINT_LABEL, &contents);
1854
1963
  if (is_extension()) {
1855
 
     contents.append("}\n");
 
1964
    contents.append("}\n");
1856
1965
  }
1857
1966
  return contents;
1858
1967
}
1859
1968
 
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()) {
1871
1982
      field_type = kTypeToName[type()];
1872
1983
  }
1873
1984
 
1874
 
  strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4",
 
1985
  string label;
 
1986
  if (print_label_flag == PRINT_LABEL) {
 
1987
    label = kLabelToName[this->label()];
 
1988
    label.push_back(' ');
 
1989
  }
 
1990
 
 
1991
  strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4",
1875
1992
                               prefix,
1876
 
                               kLabelToName[label()],
 
1993
                               label,
1877
1994
                               field_type,
1878
1995
                               type() == TYPE_GROUP ? message_type()->name() :
1879
1996
                                                      name(),
1904
2021
  }
1905
2022
}
1906
2023
 
 
2024
string OneofDescriptor::DebugString() const {
 
2025
  string contents;
 
2026
  DebugString(0, &contents);
 
2027
  return contents;
 
2028
}
 
2029
 
 
2030
void OneofDescriptor::DebugString(int depth, string* contents) const {
 
2031
  string prefix(depth * 2, ' ');
 
2032
  ++depth;
 
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);
 
2037
  }
 
2038
  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
 
2039
}
 
2040
 
1907
2041
string EnumDescriptor::DebugString() const {
1908
2042
  string contents;
1909
2043
  DebugString(0, &contents);
1986
2120
 
1987
2121
// Location methods ===============================================
1988
2122
 
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;
1993
 
  }
1994
 
  return true;
1995
 
}
1996
 
 
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);
2009
2135
 
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();
2012
2138
        return true;
2013
2139
      }
2014
2140
    }
2032
2158
  return file()->GetSourceLocation(path, out_location);
2033
2159
}
2034
2160
 
 
2161
bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
 
2162
  vector<int> path;
 
2163
  GetLocationPath(&path);
 
2164
  return containing_type()->file()->GetSourceLocation(path, out_location);
 
2165
}
 
2166
 
2035
2167
bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2036
2168
  vector<int> path;
2037
2169
  GetLocationPath(&path);
2069
2201
}
2070
2202
 
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());
 
2208
    } else {
 
2209
      extension_scope()->GetLocationPath(output);
 
2210
      output->push_back(DescriptorProto::kExtensionFieldNumber);
 
2211
      output->push_back(index());
 
2212
    }
 
2213
  } else {
 
2214
    containing_type()->GetLocationPath(output);
 
2215
    output->push_back(DescriptorProto::kFieldFieldNumber);
 
2216
    output->push_back(index());
 
2217
  }
 
2218
}
 
2219
 
 
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());
2075
2224
}
2076
2225
 
2156
2305
  FileDescriptorTables* file_tables_;
2157
2306
  set<const FileDescriptor*> dependencies_;
2158
2307
 
 
2308
  // unused_dependency_ is used to record the unused imported files.
 
2309
  // Note: public import is not considered.
 
2310
  set<const FileDescriptor*> unused_dependency_;
 
2311
 
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_;
2168
2321
 
 
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_;
 
2326
 
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,
 
2334
                const char* error);
 
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);
2173
2338
 
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);
2181
2346
 
 
2347
  void AddWarning(const string& element_name, const Message& descriptor,
 
2348
                  DescriptorPool::ErrorCollector::ErrorLocation location,
 
2349
                  const string& error);
 
2350
 
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,
 
2486
                  Descriptor* parent,
 
2487
                  OneofDescriptor* result);
2316
2488
  void BuildEnum(const EnumDescriptorProto& proto,
2317
2489
                 const Descriptor* parent,
2318
2490
                 EnumDescriptor* result);
2326
2498
                   const ServiceDescriptor* parent,
2327
2499
                   MethodDescriptor* result);
2328
2500
 
 
2501
  void LogUnusedDependency(const FileDescriptor* result);
 
2502
 
2329
2503
  // Must be run only after building.
2330
2504
  //
2331
2505
  // NOTE: Options will not be available during cross-linking, as they
2461
2635
  static inline bool get_allow_unknown(const DescriptorPool* pool) {
2462
2636
    return pool->allow_unknown_;
2463
2637
  }
 
2638
  static inline bool get_enforce_weak(const DescriptorPool* pool) {
 
2639
    return pool->enforce_weak_;
 
2640
  }
2464
2641
  static inline bool get_is_placeholder(const Descriptor* descriptor) {
2465
2642
    return descriptor->is_placeholder_;
2466
2643
  }
2503
2680
       "DescriptorDatabase.  You must instead find a way to get your file "
2504
2681
       "into the underlying database.";
2505
2682
  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
 
2683
  tables_->known_bad_symbols_.clear();
 
2684
  tables_->known_bad_files_.clear();
2506
2685
  return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
2507
2686
}
2508
2687
 
2514
2693
       "DescriptorDatabase.  You must instead find a way to get your file "
2515
2694
       "into the underlying database.";
2516
2695
  GOOGLE_CHECK(mutex_ == NULL);   // Implied by the above GOOGLE_CHECK.
 
2696
  tables_->known_bad_symbols_.clear();
 
2697
  tables_->known_bad_files_.clear();
2517
2698
  return DescriptorBuilder(this, tables_.get(),
2518
2699
                           error_collector).BuildFile(proto);
2519
2700
}
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) {
 
2706
    return NULL;
 
2707
  }
 
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());
 
2713
  }
 
2714
  return result;
2526
2715
}
2527
2716
 
2528
2717
DescriptorBuilder::DescriptorBuilder(
2533
2722
    tables_(tables),
2534
2723
    error_collector_(error_collector),
2535
2724
    had_errors_(false),
2536
 
    possible_undeclared_dependency_(NULL) {}
 
2725
    possible_undeclared_dependency_(NULL),
 
2726
    undefine_resolved_name_("") {}
2537
2727
 
2538
2728
DescriptorBuilder::~DescriptorBuilder() {}
2539
2729
 
2555
2745
  had_errors_ = true;
2556
2746
}
2557
2747
 
 
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));
 
2754
}
 
2755
 
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.");
2566
2765
  } else {
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.");
 
2773
    }
 
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.");
 
2782
    }
 
2783
  }
 
2784
}
 
2785
 
 
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;
 
2792
  } else {
 
2793
    error_collector_->AddWarning(filename_, element_name, &descriptor, location,
 
2794
                                 error);
2573
2795
  }
2574
2796
}
2575
2797
 
2630
2852
  // Only find symbols which were defined in this file or one of its
2631
2853
  // dependencies.
2632
2854
  const FileDescriptor* file = result.GetFile();
2633
 
  if (file == file_ || dependencies_.count(file) > 0) return result;
 
2855
  if (file == file_ || dependencies_.count(file) > 0) {
 
2856
    unused_dependency_.erase(file);
 
2857
    return result;
 
2858
  }
2634
2859
 
2635
2860
  if (result.type == Symbol::PACKAGE) {
2636
2861
    // Arg, this is overcomplicated.  The symbol is a package name.  It could
2656
2881
Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
2657
2882
    const string& name, const string& relative_to, ResolveMode resolve_mode) {
2658
2883
  possible_undeclared_dependency_ = NULL;
 
2884
  undefine_resolved_name_.clear();
2659
2885
 
2660
2886
  if (name.size() > 0 && name[0] == '.') {
2661
2887
    // Fully-qualified name.
2704
2930
        if (result.IsAggregate()) {
2705
2931
          scope_to_try.append(name, first_part_of_name.size(),
2706
2932
                              name.size() - first_part_of_name.size());
2707
 
          return FindSymbol(scope_to_try);
 
2933
          result = FindSymbol(scope_to_try);
 
2934
          if (result.IsNull()) {
 
2935
            undefine_resolved_name_ = scope_to_try;
 
2936
          }
 
2937
          return result;
2708
2938
        } else {
2709
2939
          // We found a symbol but it's not an aggregate.  Continue the loop.
2710
2940
        }
2757
2987
    placeholder_name = tables_->AllocateString(
2758
2988
      placeholder_full_name->substr(dotpos + 1));
2759
2989
  } else {
2760
 
    placeholder_package = &kEmptyString;
 
2990
    placeholder_package = &internal::GetEmptyString();
2761
2991
    placeholder_name = placeholder_full_name;
2762
2992
  }
2763
2993
 
2773
3003
  placeholder_file->pool_ = pool_;
2774
3004
  placeholder_file->options_ = &FileOptions::default_instance();
2775
3005
  placeholder_file->tables_ = &FileDescriptorTables::kEmpty;
 
3006
  placeholder_file->is_placeholder_ = true;
2776
3007
  // All other fields are zero or NULL.
2777
3008
 
2778
3009
  if (placeholder_type == PLACEHOLDER_ENUM) {
2843
3074
  memset(placeholder, 0, sizeof(*placeholder));
2844
3075
 
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.
2851
3083
 
2852
3084
  return placeholder;
3017
3249
    METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i);             \
3018
3250
  }
3019
3251
 
 
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(" -> ");
 
3258
  }
 
3259
  error_message.append(proto.name());
 
3260
 
 
3261
  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
 
3262
           error_message);
 
3263
}
 
3264
 
 
3265
void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
 
3266
                                            int index) {
 
3267
  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
 
3268
           "Import \"" + proto.dependency(index) + "\" was listed twice.");
 
3269
}
 
3270
 
 
3271
void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
 
3272
                                       int index) {
 
3273
  string message;
 
3274
  if (pool_->fallback_database_ == NULL) {
 
3275
    message = "Import \"" + proto.dependency(index) +
 
3276
              "\" has not been loaded.";
 
3277
  } else {
 
3278
    message = "Import \"" + proto.dependency(index) +
 
3279
              "\" was not found or had errors.";
 
3280
  }
 
3281
  AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message);
 
3282
}
 
3283
 
 
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();
 
3289
}
 
3290
 
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;
3037
3306
    }
3050
3319
  //   at all.
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(" -> ");
3057
 
      }
3058
 
      error_message.append(proto.name());
3059
 
 
3060
 
      AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
3061
 
               error_message);
 
3322
      AddRecursiveImportError(proto, i);
3062
3323
      return NULL;
3063
3324
    }
3064
3325
  }
3085
3346
  FileDescriptor* result = tables_->Allocate<FileDescriptor>();
3086
3347
  file_ = result;
3087
3348
 
 
3349
  result->is_placeholder_ = false;
3088
3350
  if (proto.has_source_code_info()) {
3089
3351
    SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
3090
3352
    info->CopyFrom(proto.source_code_info());
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();
 
3397
  set<int> weak_deps;
 
3398
  for (int i = 0; i < proto.weak_dependency_size(); ++i) {
 
3399
    weak_deps.insert(proto.weak_dependency(i));
 
3400
  }
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);
3139
3404
    }
3140
3405
 
3141
3406
    const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
3144
3409
    }
3145
3410
 
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));
3149
3415
      } else {
3150
 
        string message;
3151
 
        if (pool_->fallback_database_ == NULL) {
3152
 
          message = "Import \"" + proto.dependency(i) +
3153
 
                    "\" has not been loaded.";
3154
 
        } else {
3155
 
          message = "Import \"" + proto.dependency(i) +
3156
 
                    "\" was not found or had errors.";
3157
 
        }
3158
 
        AddError(proto.name(), proto,
3159
 
                 DescriptorPool::ErrorCollector::OTHER,
3160
 
                 message);
 
3416
        AddImportError(proto, i);
 
3417
      }
 
3418
    } else {
 
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);
3161
3426
      }
3162
3427
    }
3163
3428
 
3173
3438
    int index = proto.public_dependency(i);
3174
3439
    if (index >= 0 && index < proto.dependency_size()) {
3175
3440
      result->public_dependencies_[public_dependency_count++] = index;
 
3441
      // Do not track unused imported files for public import.
 
3442
      unused_dependency_.erase(result->dependency(index));
3176
3443
    } else {
3177
3444
      AddError(proto.name(), proto,
3178
3445
               DescriptorPool::ErrorCollector::OTHER,
3239
3506
    ValidateFileOptions(result, proto);
3240
3507
  }
3241
3508
 
 
3509
 
 
3510
  if (!unused_dependency_.empty()) {
 
3511
    LogUnusedDependency(result);
 
3512
  }
 
3513
 
3242
3514
  if (had_errors_) {
3243
3515
    tables_->RollbackToLastCheckpoint();
3244
3516
    return NULL;
3266
3538
  result->is_placeholder_  = false;
3267
3539
  result->is_unqualified_placeholder_ = false;
3268
3540
 
 
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()));
3358
3632
 
 
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.");
 
3644
  }
 
3645
 
3359
3646
  // Some of these may be filled in when cross-linking.
3360
3647
  result->containing_type_ = NULL;
3361
3648
  result->extension_scope_ = NULL;
3399
3686
            result->default_value_float_ = numeric_limits<float>::quiet_NaN();
3400
3687
          } else  {
3401
3688
            result->default_value_float_ =
3402
 
              NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
 
3689
              io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
3403
3690
          }
3404
3691
          break;
3405
3692
        case FieldDescriptor::CPPTYPE_DOUBLE:
3411
3698
            result->default_value_double_ = numeric_limits<double>::quiet_NaN();
3412
3699
          } else  {
3413
3700
            result->default_value_double_ =
3414
 
              NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
 
3701
                io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
3415
3702
          }
3416
3703
          break;
3417
3704
        case FieldDescriptor::CPPTYPE_BOOL:
3453
3740
        if (proto.default_value().empty() || *end_pos != '\0') {
3454
3741
          AddError(result->full_name(), proto,
3455
3742
                   DescriptorPool::ErrorCollector::DEFAULT_VALUE,
3456
 
                   "Couldn't parse default value.");
 
3743
                   "Couldn't parse default value \"" + proto.default_value() +
 
3744
                   "\".");
3457
3745
        }
3458
3746
      }
3459
3747
    } else {
3485
3773
          result->default_value_enum_ = NULL;
3486
3774
          break;
3487
3775
        case FieldDescriptor::CPPTYPE_STRING:
3488
 
          result->default_value_string_ = &kEmptyString;
 
3776
          result->default_value_string_ = &internal::GetEmptyString();
3489
3777
          break;
3490
3778
        case FieldDescriptor::CPPTYPE_MESSAGE:
3491
3779
          break;
3526
3814
    }
3527
3815
 
3528
3816
    result->extension_scope_ = parent;
 
3817
 
 
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 "
 
3822
               "extensions.");
 
3823
    }
 
3824
 
 
3825
    // Fill in later (maybe).
 
3826
    result->containing_oneof_ = NULL;
3529
3827
  } else {
3530
3828
    if (proto.has_extendee()) {
3531
3829
      AddError(result->full_name(), proto,
3534
3832
    }
3535
3833
 
3536
3834
    result->containing_type_ = parent;
 
3835
 
 
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(),
 
3844
                                     parent->name()));
 
3845
        result->containing_oneof_ = NULL;
 
3846
      } else {
 
3847
        result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
 
3848
      }
 
3849
    } else {
 
3850
      result->containing_oneof_ = NULL;
 
3851
    }
3537
3852
  }
3538
3853
 
3539
3854
  // Copy options.
3571
3886
  }
3572
3887
}
3573
3888
 
 
3889
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
 
3890
                                   Descriptor* parent,
 
3891
                                   OneofDescriptor* result) {
 
3892
  string* full_name = tables_->AllocateString(parent->full_name());
 
3893
  full_name->append(1, '.');
 
3894
  full_name->append(proto.name());
 
3895
 
 
3896
  ValidateSymbolName(proto.name(), *full_name, proto);
 
3897
 
 
3898
  result->name_ = tables_->AllocateString(proto.name());
 
3899
  result->full_name_ = full_name;
 
3900
 
 
3901
  result->containing_type_ = parent;
 
3902
 
 
3903
  // We need to fill these in later.
 
3904
  result->field_count_ = 0;
 
3905
  result->fields_ = NULL;
 
3906
 
 
3907
  AddSymbol(result->full_name(), parent, result->name(),
 
3908
            proto, Symbol(result));
 
3909
}
 
3910
 
3574
3911
void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
3575
3912
                                  const Descriptor* parent,
3576
3913
                                  EnumDescriptor* result) {
3679
4016
}
3680
4017
 
3681
4018
void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
3682
 
                                     const void* dummy,
 
4019
                                     const void* /* dummy */,
3683
4020
                                     ServiceDescriptor* result) {
3684
4021
  string* full_name = tables_->AllocateString(file_->package());
3685
4022
  if (!full_name->empty()) full_name->append(1, '.');
3780
4117
  for (int i = 0; i < message->extension_count(); i++) {
3781
4118
    CrossLinkField(&message->extensions_[i], proto.extension(i));
3782
4119
  }
 
4120
 
 
4121
  // Set up field array for each oneof.
 
4122
 
 
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
 
4128
      // OneofDescriptor.
 
4129
      ++message->oneof_decls_[oneof_decl->index()].field_count_;
 
4130
    }
 
4131
  }
 
4132
 
 
4133
  // Then allocate the arrays.
 
4134
  for (int i = 0; i < message->oneof_decl_count(); i++) {
 
4135
    OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
 
4136
 
 
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.");
 
4142
    }
 
4143
 
 
4144
    oneof_decl->fields_ =
 
4145
      tables_->AllocateArray<const FieldDescriptor*>(oneof_decl->field_count_);
 
4146
    oneof_decl->field_count_ = 0;
 
4147
  }
 
4148
 
 
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_++] =
 
4157
          message->field(i);
 
4158
    }
 
4159
  }
3783
4160
}
3784
4161
 
3785
4162
void DescriptorBuilder::CrossLinkField(
3804
4181
    }
3805
4182
    field->containing_type_ = extendee.descriptor;
3806
4183
 
3807
 
    if (!field->containing_type()->IsExtensionNumber(field->number())) {
 
4184
    const Descriptor::ExtensionRange* extension_range = field->containing_type()
 
4185
        ->FindExtensionRangeContainingNumber(field->number());
 
4186
 
 
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 "
3814
4194
    }
3815
4195
  }
3816
4196
 
 
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.");
 
4205
    }
 
4206
  }
 
4207
 
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,
3827
4218
                   LOOKUP_TYPES);
3828
4219
 
 
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);
 
4223
    }
 
4224
 
3829
4225
    if (type.IsNull()) {
3830
4226
      AddNotDefinedError(field->full_name(), proto,
3831
4227
                         DescriptorPool::ErrorCollector::TYPE,
3877
4273
      }
3878
4274
 
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
3882
 
        // at this point.
3883
 
        Symbol default_value =
3884
 
          LookupSymbolNoPlaceholder(proto.default_value(),
3885
 
                                    field->enum_type()->full_name());
3886
 
 
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;
3890
 
        } else {
 
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.");
 
4285
        } else {
 
4286
          // We can't just use field->enum_type()->FindValueByName() here
 
4287
          // because that locks the pool's mutex, which we have already locked
 
4288
          // at this point.
 
4289
          Symbol default_value =
 
4290
            LookupSymbolNoPlaceholder(proto.default_value(),
 
4291
                                      field->enum_type()->full_name());
 
4292
 
 
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;
 
4297
          } else {
 
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() +
 
4302
                     "\".");
 
4303
          }
3895
4304
        }
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()));
3937
4346
    }
3938
 
  }
3939
 
 
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);
 
4347
  } else {
 
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.",
 
4355
            field->number(),
 
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
 
4361
        // protos first.
 
4362
        // TODO(xiaofeng): Change this to an error.
 
4363
        AddWarning(field->full_name(), proto,
 
4364
                   DescriptorPool::ErrorCollector::NUMBER, error_msg);
 
4365
      }
 
4366
    }
3944
4367
  }
3945
4368
 
3946
4369
  // Add the field to the lowercase-name and camelcase-name tables.
3959
4382
}
3960
4383
 
3961
4384
void DescriptorBuilder::CrossLinkEnumValue(
3962
 
    EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) {
 
4385
    EnumValueDescriptor* enum_value,
 
4386
    const EnumValueDescriptorProto& /* proto */) {
3963
4387
  if (enum_value->options_ == NULL) {
3964
4388
    enum_value->options_ = &EnumValueOptions::default_instance();
3965
4389
  }
4023
4447
  // TODO(kenton):  I don't even remember how many of these conditions are
4024
4448
  //   actually possible.  I'm just being super-safe.
4025
4449
  return file != NULL &&
4026
 
         &file->options() != NULL &&
4027
4450
         &file->options() != &FileOptions::default_instance() &&
4028
4451
         file->options().optimize_for() == FileOptions::LITE_RUNTIME;
4029
4452
}
4051
4474
  }
4052
4475
}
4053
4476
 
 
4477
 
4054
4478
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
4055
4479
                                               const DescriptorProto& proto) {
4056
4480
  VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
4160
4584
}
4161
4585
 
4162
4586
void DescriptorBuilder::ValidateEnumValueOptions(
4163
 
    EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) {
 
4587
    EnumValueDescriptor* /* enum_value */,
 
4588
    const EnumValueDescriptorProto& /* proto */) {
4164
4589
  // Nothing to do so far.
4165
4590
}
4166
4591
void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
4178
4603
  VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
4179
4604
}
4180
4605
 
4181
 
void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* method,
4182
 
    const MethodDescriptorProto& proto) {
 
4606
void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */,
 
4607
    const MethodDescriptorProto& /* proto */) {
4183
4608
  // Nothing to do so far.
4184
4609
}
4185
4610
 
4388
4813
        // so we will just leave it as uninterpreted.
4389
4814
        AddWithoutInterpreting(*uninterpreted_option_, options);
4390
4815
        return true;
 
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.");
4391
4825
      } else {
4392
4826
        return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
4393
4827
      }
4408
4842
                            "\" is not a field or extension of message \"" +
4409
4843
                            descriptor->name() + "\".");
4410
4844
      }
4411
 
    } else if (field->is_repeated()) {
4412
 
      return AddNameError("Option field \"" + debug_msg_name +
4413
 
                          "\" is repeated. Repeated options are not "
4414
 
                          "supported.");
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.");
4419
4854
      } else {
4420
4855
        // Drill down into the submessage.
4421
4856
        intermediate_fields.push_back(field);
4432
4867
  // known will populate them correctly.
4433
4868
 
4434
4869
  // First see if the option is already set.
4435
 
  if (!ExamineIfOptionIsSet(
 
4870
  if (!field->is_repeated() && !ExamineIfOptionIsSet(
4436
4871
          intermediate_fields.begin(),
4437
4872
          intermediate_fields.end(),
4438
4873
          field, debug_msg_name,
4807
5242
 public:
4808
5243
  string error_;
4809
5244
 
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_ += "; ";
4813
5249
    }
4814
5250
    error_ += message;
4815
5251
  }
4816
5252
 
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
4819
5256
  }
4820
5257
};
4945
5382
  }
4946
5383
}
4947
5384
 
 
5385
void DescriptorBuilder::LogUnusedDependency(const FileDescriptor* result) {
 
5386
 
 
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.
 
5401
      int i;
 
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()) {
 
5406
          break;
 
5407
        }
 
5408
      }
 
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.";
 
5414
      }
 
5415
    }
 
5416
  }
 
5417
}
 
5418
 
4948
5419
}  // namespace protobuf
4949
5420
}  // namespace google