Support GenerateAll().

- Expect calls on GenerateAll() and not Generate().
- Parse the prefix validation file once, and then check all the files.
This commit is contained in:
Thomas Van Lenten 2016-08-24 17:29:05 -04:00
parent b97a4a53cd
commit 2e66a61b54
5 changed files with 98 additions and 58 deletions

View File

@ -99,26 +99,26 @@ CORE_PROTO_FILES+=(
src/google/protobuf/descriptor.proto
)
compile_proto() {
compile_protos() {
src/protoc \
--objc_out="${OUTPUT_DIR}/google/protobuf" \
--proto_path=src/google/protobuf/ \
--proto_path=src \
$*
"$@"
}
# Note: there is overlap in package.Message names between some of the test
# files, so they can't be generated all at once. This works because the overlap
# isn't linked into a single binary.
for a_proto in "${CORE_PROTO_FILES[@]}" ; do
compile_proto "${a_proto}"
compile_protos "${a_proto}"
done
OBJC_PROTO_FILES=(
objectivec/Tests/unittest_cycle.proto
objectivec/Tests/unittest_runtime_proto2.proto
objectivec/Tests/unittest_runtime_proto3.proto
objectivec/Tests/unittest_objc.proto
# Objective C specific testing protos.
compile_protos \
--proto_path="objectivec/Tests" \
objectivec/Tests/unittest_cycle.proto \
objectivec/Tests/unittest_runtime_proto2.proto \
objectivec/Tests/unittest_runtime_proto3.proto \
objectivec/Tests/unittest_objc.proto \
objectivec/Tests/unittest_objc_startup.proto
)
for a_proto in "${OBJC_PROTO_FILES[@]}" ; do
compile_proto --proto_path="objectivec/Tests" "${a_proto}"
done

View File

@ -45,10 +45,22 @@ ObjectiveCGenerator::ObjectiveCGenerator() {}
ObjectiveCGenerator::~ObjectiveCGenerator() {}
bool ObjectiveCGenerator::HasGenerateAll() const {
return true;
}
bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
const string& parameter,
OutputDirectory* output_directory,
GeneratorContext* context,
string* error) const {
*error = "Unimplemented Generate() method. Call GenerateAll() instead.";
return false;
}
bool ObjectiveCGenerator::GenerateAll(const vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* context,
string* error) const {
// -----------------------------------------------------------------
// Parse generator options. These options are passed to the compiler using the
// --objc_opt flag. The options are passed as a comma separated list of
@ -117,29 +129,32 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
// -----------------------------------------------------------------
// Validate the objc prefix/package pairing.
if (!ValidateObjCClassPrefix(file, generation_options, error)) {
// Validate the objc prefix/package pairings.
if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
// *error will have been filled in.
return false;
}
FileGenerator file_generator(file, generation_options);
string filepath = FilePath(file);
for (int i = 0; i < files.size(); i++) {
const FileDescriptor* file = files[i];
FileGenerator file_generator(file, generation_options);
string filepath = FilePath(file);
// Generate header.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(filepath + ".pbobjc.h"));
io::Printer printer(output.get(), '$');
file_generator.GenerateHeader(&printer);
}
// Generate header.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
context->Open(filepath + ".pbobjc.h"));
io::Printer printer(output.get(), '$');
file_generator.GenerateHeader(&printer);
}
// Generate m file.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(filepath + ".pbobjc.m"));
io::Printer printer(output.get(), '$');
file_generator.GenerateSource(&printer);
// Generate m file.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
context->Open(filepath + ".pbobjc.m"));
io::Printer printer(output.get(), '$');
file_generator.GenerateSource(&printer);
}
}
return true;

View File

@ -47,8 +47,15 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
~ObjectiveCGenerator();
// implements CodeGenerator ----------------------------------------
bool Generate(const FileDescriptor* file, const string& parameter,
OutputDirectory* output_directory, string* error) const;
bool HasGenerateAll() const;
bool Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* context,
string* error) const;
bool GenerateAll(const vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* context,
string* error) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);

View File

@ -980,28 +980,20 @@ bool LoadExpectedPackagePrefixes(const Options &generation_options,
generation_options.expected_prefixes_path, &collector, out_error);
}
} // namespace
bool ValidateObjCClassPrefix(const FileDescriptor* file,
const Options& generation_options,
string* out_error) {
bool ValidateObjCClassPrefix(
const FileDescriptor* file,
const string& expected_prefixes_path,
const map<string, string>& expected_package_prefixes,
string* out_error) {
const string prefix = file->options().objc_class_prefix();
const string package = file->package();
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for warnings.
// Load any expected package prefixes to validate against those.
map<string, string> expected_package_prefixes;
if (!LoadExpectedPackagePrefixes(generation_options,
&expected_package_prefixes,
out_error)) {
return false;
}
// Check: Error - See if there was an expected prefix for the package and
// report if it doesn't match (wrong or missing).
map<string, string>::iterator package_match =
map<string, string>::const_iterator package_match =
expected_package_prefixes.find(package);
if (package_match != expected_package_prefixes.end()) {
// There was an entry, and...
@ -1050,7 +1042,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
// Look for any other package that uses the same prefix.
string other_package_for_prefix;
for (map<string, string>::iterator i = expected_package_prefixes.begin();
for (map<string, string>::const_iterator i = expected_package_prefixes.begin();
i != expected_package_prefixes.end(); ++i) {
if (i->second == prefix) {
other_package_for_prefix = i->first;
@ -1068,7 +1060,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
<< "protoc:0: warning: File '" << file->name() << "' has no "
<< "package. Consider adding a new package to the proto and adding '"
<< "new.package = " << prefix << "' to the expected prefixes file ("
<< generation_options.expected_prefixes_path << ")." << endl;
<< expected_prefixes_path << ")." << endl;
cerr.flush();
} else {
// ... another package has declared the same prefix.
@ -1078,7 +1070,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
<< prefix << "' as its prefix. Consider either adding a new package "
<< "to the proto, or reusing one of the packages already using this "
<< "prefix in the expected prefixes file ("
<< generation_options.expected_prefixes_path << ")." << endl;
<< expected_prefixes_path << ")." << endl;
cerr.flush();
}
return true;
@ -1094,7 +1086,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
"'; that prefix is already used for 'package " +
other_package_for_prefix + ";'. It can only be reused by listing " +
"it in the expected file (" +
generation_options.expected_prefixes_path + ").";
expected_prefixes_path + ").";
return false; // Only report first usage of the prefix.
}
@ -1105,13 +1097,39 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file,
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " consider adding it to the expected prefixes file ("
<< generation_options.expected_prefixes_path << ")." << endl;
<< expected_prefixes_path << ")." << endl;
cerr.flush();
}
return true;
}
} // namespace
bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
const Options& generation_options,
string* out_error) {
// Load the expected package prefixes, if available, to validate against.
map<string, string> expected_package_prefixes;
if (!LoadExpectedPackagePrefixes(generation_options,
&expected_package_prefixes,
out_error)) {
return false;
}
for (int i = 0; i < files.size(); i++) {
bool is_valid =
ValidateObjCClassPrefix(files[i],
generation_options.expected_prefixes_path,
expected_package_prefixes,
out_error);
if (!is_valid) {
return false;
}
}
return true;
}
TextFormatDecodeData::TextFormatDecodeData() { }
TextFormatDecodeData::~TextFormatDecodeData() { }

View File

@ -185,12 +185,12 @@ string ProtobufFrameworkImportSymbol(const string& framework_name);
// Checks if the file is one of the proto's bundled with the library.
bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
// Checks the prefix for a given file and outputs any warnings needed, if
// there are flat out errors, then out_error is filled in and the result is
// false.
bool ValidateObjCClassPrefix(const FileDescriptor* file,
const Options& generation_options,
string* out_error);
// Checks the prefix for the given files and outputs any warnings as needed. If
// there are flat out errors, then out_error is filled in with the first error
// and the result is false.
bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
const Options& generation_options,
string* out_error);
// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
// the input into the expected output.