|  | @@ -937,41 +937,17 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
 | 
	
		
			
				|  |  |    // 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.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // First Check: Warning - if there is a prefix, ensure it is is a reasonable
 | 
	
		
			
				|  |  | -  // value according to Apple's rules.
 | 
	
		
			
				|  |  | -  if (prefix.length()) {
 | 
	
		
			
				|  |  | -    if (!ascii_isupper(prefix[0])) {
 | 
	
		
			
				|  |  | -      cerr << endl
 | 
	
		
			
				|  |  | -           << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
 | 
	
		
			
				|  |  | -           << prefix << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | -           << " it should start with a capital letter." << endl;
 | 
	
		
			
				|  |  | -      cerr.flush();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (prefix.length() < 3) {
 | 
	
		
			
				|  |  | -      cerr << endl
 | 
	
		
			
				|  |  | -           << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
 | 
	
		
			
				|  |  | -           << prefix << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | -           << " Apple recommends they should be at least 3 characters long."
 | 
	
		
			
				|  |  | -           << endl;
 | 
	
		
			
				|  |  | -      cerr.flush();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    // Load any expected package prefixes to validate against those.
 | 
	
		
			
				|  |  |    map<string, string> expected_package_prefixes;
 | 
	
		
			
				|  |  |    string expect_file_path;
 | 
	
		
			
				|  |  |    if (!LoadExpectedPackagePrefixes(&expected_package_prefixes,
 | 
	
		
			
				|  |  |                                     &expect_file_path, out_error)) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | +    // Any error, clear the entries that were read.
 | 
	
		
			
				|  |  | +    expected_package_prefixes.clear();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // If there are no expected prefixes, out of here.
 | 
	
		
			
				|  |  | -  if (expected_package_prefixes.size() == 0) {
 | 
	
		
			
				|  |  | -    return true;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Second Check: Error - See if there was an expected prefix for the package
 | 
	
		
			
				|  |  | -  // and report if it doesn't match.
 | 
	
		
			
				|  |  | +  // 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 =
 | 
	
		
			
				|  |  |        expected_package_prefixes.find(package);
 | 
	
		
			
				|  |  |    if (package_match != expected_package_prefixes.end()) {
 | 
	
	
		
			
				|  | @@ -991,32 +967,57 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Third Check: Error - If there was a prefix make sure it wasn't expected
 | 
	
		
			
				|  |  | -  // for a different package instead (overlap is allowed, but it has to be
 | 
	
		
			
				|  |  | -  // listed as an expected overlap).
 | 
	
		
			
				|  |  | -  if (prefix.length()) {
 | 
	
		
			
				|  |  | -    for (map<string, string>::iterator i = expected_package_prefixes.begin();
 | 
	
		
			
				|  |  | -         i != expected_package_prefixes.end(); ++i) {
 | 
	
		
			
				|  |  | -      if (i->second == prefix) {
 | 
	
		
			
				|  |  | -        *out_error =
 | 
	
		
			
				|  |  | -            "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix +
 | 
	
		
			
				|  |  | -            "\";' in '" + file->name() +
 | 
	
		
			
				|  |  | -            "'; that prefix is already used for 'package " + i->first +
 | 
	
		
			
				|  |  | -            ";'. It can only be reused by listing it in the expected file (" +
 | 
	
		
			
				|  |  | -            expect_file_path + ").";
 | 
	
		
			
				|  |  | -        return false;  // Only report first usage of the prefix.
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +  // If there was no prefix option, we're done at this point.
 | 
	
		
			
				|  |  | +  if (prefix.length() == 0) {
 | 
	
		
			
				|  |  | +    // No prefix, nothing left to check.
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Check: Error - Make sure the prefix wasn't expected for a different
 | 
	
		
			
				|  |  | +  // package (overlap is allowed, but it has to be listed as an expected
 | 
	
		
			
				|  |  | +  // overlap).
 | 
	
		
			
				|  |  | +  for (map<string, string>::iterator i = expected_package_prefixes.begin();
 | 
	
		
			
				|  |  | +       i != expected_package_prefixes.end(); ++i) {
 | 
	
		
			
				|  |  | +    if (i->second == prefix) {
 | 
	
		
			
				|  |  | +      *out_error =
 | 
	
		
			
				|  |  | +          "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix +
 | 
	
		
			
				|  |  | +          "\";' in '" + file->name() +
 | 
	
		
			
				|  |  | +          "'; that prefix is already used for 'package " + i->first +
 | 
	
		
			
				|  |  | +          ";'. It can only be reused by listing it in the expected file (" +
 | 
	
		
			
				|  |  | +          expect_file_path + ").";
 | 
	
		
			
				|  |  | +      return false;  // Only report first usage of the prefix.
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Fourth Check: Warning - If there was a prefix, and it wasn't expected,
 | 
	
		
			
				|  |  | -  // issue a warning suggesting it gets added to the file.
 | 
	
		
			
				|  |  | -  if (prefix.length()) {
 | 
	
		
			
				|  |  | +  // Check: Warning - Make sure the prefix is is a reasonable value according
 | 
	
		
			
				|  |  | +  // to Apple's rules (the checks above implicitly whitelist anything that
 | 
	
		
			
				|  |  | +  // doesn't meet these rules).
 | 
	
		
			
				|  |  | +  if (!ascii_isupper(prefix[0])) {
 | 
	
		
			
				|  |  | +    cerr << endl
 | 
	
		
			
				|  |  | +         << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
 | 
	
		
			
				|  |  | +         << prefix << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | +         << " it should start with a capital letter." << endl;
 | 
	
		
			
				|  |  | +    cerr.flush();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (prefix.length() < 3) {
 | 
	
		
			
				|  |  | +    // Apple reserves 2 character prefixes for themselves. They do use some
 | 
	
		
			
				|  |  | +    // 3 character prefixes, but they haven't updated the rules/docs.
 | 
	
		
			
				|  |  | +    cerr << endl
 | 
	
		
			
				|  |  | +         << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
 | 
	
		
			
				|  |  | +         << prefix << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | +         << " Apple recommends they should be at least 3 characters long."
 | 
	
		
			
				|  |  | +         << endl;
 | 
	
		
			
				|  |  | +    cerr.flush();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Check: Warning - If the given package/prefix pair wasn't expected, issue a
 | 
	
		
			
				|  |  | +  // warning issue a warning suggesting it gets added to the file.
 | 
	
		
			
				|  |  | +  if (!expected_package_prefixes.empty()) {
 | 
	
		
			
				|  |  |      cerr << endl
 | 
	
		
			
				|  |  | -         << "protoc:0: warning: Found 'option objc_class_prefix = \"" << prefix
 | 
	
		
			
				|  |  | -         << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | -         << " should you add it to the expected prefixes file ("
 | 
	
		
			
				|  |  | -         << expect_file_path << ")?" << endl;
 | 
	
		
			
				|  |  | +         << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
 | 
	
		
			
				|  |  | +         << prefix << "\";' in '" << file->name() << "';"
 | 
	
		
			
				|  |  | +         << " consider adding it to the expected prefixes file ("
 | 
	
		
			
				|  |  | +         << expect_file_path << ")." << endl;
 | 
	
		
			
				|  |  |      cerr.flush();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 |