Skip to content

Commit 5cd9a46

Browse files
mkruskal-googlecopybara-github
authored andcommitted
Limit feature deprecation warnings to reduce noise.
This builds off of our existing pattern for unused imports. We will still warn when any deprecated features are used in a proto file passed directly to protoc, but will avoid them in the following situations: 1) Transitive imports pulled from the filesystem or descriptors will not trigger warnings. This will keep warnings isolated to the upstream builds instead of alerting all downstream clients. 2) Dynamic pool builds will not log deprecation warnings by default. PiperOrigin-RevId: 663396953
1 parent 6c2be3b commit 5cd9a46

File tree

8 files changed

+184
-47
lines changed

8 files changed

+184
-47
lines changed

src/google/protobuf/compiler/command_line_interface.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,7 +1596,7 @@ bool CommandLineInterface::ParseInputFiles(
15961596
// exclusively reading from descriptor sets, we can eliminate this failure
15971597
// condition.
15981598
for (const auto& input_file : input_files_) {
1599-
descriptor_pool->AddUnusedImportTrackFile(input_file);
1599+
descriptor_pool->AddDirectInputFile(input_file);
16001600
}
16011601
}
16021602

@@ -1643,7 +1643,7 @@ bool CommandLineInterface::ParseInputFiles(
16431643
}
16441644
}
16451645
}
1646-
descriptor_pool->ClearUnusedImportTrackFiles();
1646+
descriptor_pool->ClearDirectInputFiles();
16471647
return result;
16481648
}
16491649

src/google/protobuf/compiler/command_line_interface_unittest.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,54 @@ TEST_F(CommandLineInterfaceTest, Plugin_DeprecatedEdition) {
15511551
"edition 99997_TEST_ONLY.");
15521552
}
15531553

1554+
TEST_F(CommandLineInterfaceTest, Plugin_DeprecatedFeature) {
1555+
CreateTempFile("google/protobuf/descriptor.proto",
1556+
google::protobuf::DescriptorProto::descriptor()->file()->DebugString());
1557+
CreateTempFile("google/protobuf/unittest_features.proto",
1558+
pb::TestFeatures::descriptor()->file()->DebugString());
1559+
CreateTempFile("foo.proto",
1560+
R"schema(
1561+
edition = "2023";
1562+
import "google/protobuf/unittest_features.proto";
1563+
package foo;
1564+
option features.(pb.test).removed_feature = VALUE9;
1565+
)schema");
1566+
1567+
Run("protocol_compiler --test_out=$tmpdir "
1568+
"--proto_path=$tmpdir foo.proto");
1569+
ExpectWarningSubstring(
1570+
"foo.proto:4:5: warning: Feature pb.TestFeatures.removed_feature has "
1571+
"been deprecated in edition 2023: Custom feature deprecation warning\n");
1572+
}
1573+
1574+
TEST_F(CommandLineInterfaceTest, Plugin_TransitiveDeprecatedFeature) {
1575+
CreateTempFile("google/protobuf/descriptor.proto",
1576+
google::protobuf::DescriptorProto::descriptor()->file()->DebugString());
1577+
CreateTempFile("google/protobuf/unittest_features.proto",
1578+
pb::TestFeatures::descriptor()->file()->DebugString());
1579+
CreateTempFile("unused.proto",
1580+
R"schema(
1581+
edition = "2023";
1582+
import "google/protobuf/unittest_features.proto";
1583+
package foo;
1584+
option features.(pb.test).removed_feature = VALUE9;
1585+
message Foo {}
1586+
)schema");
1587+
CreateTempFile("foo.proto",
1588+
R"schema(
1589+
edition = "2023";
1590+
import "unused.proto";
1591+
package foo;
1592+
message Bar {
1593+
Foo foo = 1;
1594+
}
1595+
)schema");
1596+
1597+
Run("protocol_compiler --test_out=$tmpdir "
1598+
"--proto_path=$tmpdir foo.proto");
1599+
ExpectNoErrors();
1600+
}
1601+
15541602
TEST_F(CommandLineInterfaceTest, Plugin_FutureEdition) {
15551603
CreateTempFile("foo.proto", R"schema(
15561604
edition = "2023";

src/google/protobuf/compiler/importer.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,11 @@ const FileDescriptor* Importer::Import(const std::string& filename) {
216216
return pool_.FindFileByName(filename);
217217
}
218218

219-
void Importer::AddUnusedImportTrackFile(const std::string& file_name,
220-
bool is_error) {
221-
pool_.AddUnusedImportTrackFile(file_name, is_error);
219+
void Importer::AddDirectInputFile(absl::string_view file_name, bool is_error) {
220+
pool_.AddDirectInputFile(file_name, is_error);
222221
}
223222

224-
void Importer::ClearUnusedImportTrackFiles() {
225-
pool_.ClearUnusedImportTrackFiles();
226-
}
223+
void Importer::ClearDirectInputFiles() { pool_.ClearDirectInputFiles(); }
227224

228225

229226
// ===================================================================

src/google/protobuf/compiler/importer.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,19 @@ class PROTOBUF_EXPORT Importer {
159159
// contents are stored.
160160
inline const DescriptorPool* pool() const { return &pool_; }
161161

162-
void AddUnusedImportTrackFile(const std::string& file_name,
163-
bool is_error = false);
164-
void ClearUnusedImportTrackFiles();
162+
void AddDirectInputFile(absl::string_view file_name,
163+
bool unused_import_is_error = false);
164+
void ClearDirectInputFiles();
165+
166+
#if !defined(PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT) && !defined(SWIG)
167+
ABSL_DEPRECATED("Use AddDirectInputFile")
168+
void AddUnusedImportTrackFile(absl::string_view file_name,
169+
bool is_error = false) {
170+
AddDirectInputFile(file_name, is_error);
171+
}
172+
ABSL_DEPRECATED("Use AddDirectInputFile")
173+
void ClearUnusedImportTrackFiles() { ClearDirectInputFiles(); }
174+
#endif // !PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT && !SWIG
165175

166176

167177
private:

src/google/protobuf/descriptor.cc

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,14 +1382,17 @@ class DescriptorPool::DeferredValidation {
13821382
DescriptorPool::ErrorCollector::NAME, error);
13831383
}
13841384
}
1385-
for (const auto& warning : results.warnings) {
1386-
if (error_collector_ == nullptr) {
1387-
ABSL_LOG(WARNING)
1388-
<< info.filename << " " << info.full_name << ": " << warning;
1389-
} else {
1390-
error_collector_->RecordWarning(
1391-
info.filename, info.full_name, info.proto,
1392-
DescriptorPool::ErrorCollector::NAME, warning);
1385+
if (pool_->direct_input_files_.find(file->name()) !=
1386+
pool_->direct_input_files_.end()) {
1387+
for (const auto& warning : results.warnings) {
1388+
if (error_collector_ == nullptr) {
1389+
ABSL_LOG(WARNING)
1390+
<< info.filename << " " << info.full_name << ": " << warning;
1391+
} else {
1392+
error_collector_->RecordWarning(
1393+
info.filename, info.full_name, info.proto,
1394+
DescriptorPool::ErrorCollector::NAME, warning);
1395+
}
13931396
}
13941397
}
13951398
}
@@ -2132,9 +2135,9 @@ void DescriptorPool::InternalDontEnforceDependencies() {
21322135
enforce_dependencies_ = false;
21332136
}
21342137

2135-
void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
2136-
bool is_error) {
2137-
unused_import_track_files_[file_name] = is_error;
2138+
void DescriptorPool::AddDirectInputFile(absl::string_view file_name,
2139+
bool is_error) {
2140+
direct_input_files_[file_name] = is_error;
21382141
}
21392142

21402143
bool DescriptorPool::IsReadyForCheckingDescriptorExtDecl(
@@ -2155,9 +2158,7 @@ bool DescriptorPool::IsReadyForCheckingDescriptorExtDecl(
21552158
}
21562159

21572160

2158-
void DescriptorPool::ClearUnusedImportTrackFiles() {
2159-
unused_import_track_files_.clear();
2160-
}
2161+
void DescriptorPool::ClearDirectInputFiles() { direct_input_files_.clear(); }
21612162

21622163
bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const {
21632164
absl::MutexLockMaybe lock(mutex_);
@@ -6022,8 +6023,8 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl(
60226023
// Add to unused_dependency_ to track unused imported files.
60236024
// Note: do not track unused imported files for public import.
60246025
if (pool_->enforce_dependencies_ &&
6025-
(pool_->unused_import_track_files_.find(proto.name()) !=
6026-
pool_->unused_import_track_files_.end()) &&
6026+
(pool_->direct_input_files_.find(proto.name()) !=
6027+
pool_->direct_input_files_.end()) &&
60276028
(dependency->public_dependency_count() == 0)) {
60286029
unused_dependency_.insert(dependency);
60296030
}
@@ -9593,9 +9594,8 @@ void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
95939594
(void)result; // Parameter is used by Google-internal code.
95949595

95959596
if (!unused_dependency_.empty()) {
9596-
auto itr = pool_->unused_import_track_files_.find(proto.name());
9597-
bool is_error =
9598-
itr != pool_->unused_import_track_files_.end() && itr->second;
9597+
auto itr = pool_->direct_input_files_.find(proto.name());
9598+
bool is_error = itr != pool_->direct_input_files_.end() && itr->second;
95999599
for (const auto* unused : unused_dependency_) {
96009600
auto make_error = [&] {
96019601
return absl::StrCat("Import ", unused->name(), " is unused.");

src/google/protobuf/descriptor.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2370,11 +2370,23 @@ class PROTOBUF_EXPORT DescriptorPool {
23702370
// lazy descriptor initialization behavior.
23712371
bool InternalIsFileLoaded(absl::string_view filename) const;
23722372

2373-
// Add a file to unused_import_track_files_. DescriptorBuilder will log
2374-
// warnings or errors for those files if there is any unused import.
2373+
// Add a file to to apply more strict checks to.
2374+
// - unused imports will log either warnings or errors.
2375+
// - deprecated features will log warnings.
2376+
void AddDirectInputFile(absl::string_view file_name,
2377+
bool unused_import_is_error = false);
2378+
void ClearDirectInputFiles();
2379+
2380+
#if !defined(PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT) && !defined(SWIG)
2381+
ABSL_DEPRECATED("Use AddDirectInputFile")
23752382
void AddUnusedImportTrackFile(absl::string_view file_name,
2376-
bool is_error = false);
2377-
void ClearUnusedImportTrackFiles();
2383+
bool is_error = false) {
2384+
AddDirectInputFile(file_name, is_error);
2385+
}
2386+
ABSL_DEPRECATED("Use AddDirectInputFile")
2387+
void ClearUnusedImportTrackFiles() { ClearDirectInputFiles(); }
2388+
#endif // !PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT && !SWIG
2389+
23782390

23792391
private:
23802392
friend class Descriptor;
@@ -2476,9 +2488,9 @@ class PROTOBUF_EXPORT DescriptorPool {
24762488
bool deprecated_legacy_json_field_conflicts_;
24772489
mutable bool build_started_ = false;
24782490

2479-
// Set of files to track for unused imports. The bool value when true means
2480-
// unused imports are treated as errors (and as warnings when false).
2481-
absl::flat_hash_map<std::string, bool> unused_import_track_files_;
2491+
// Set of files to track for additional validation. The bool value when true
2492+
// means unused imports are treated as errors (and as warnings when false).
2493+
absl::flat_hash_map<std::string, bool> direct_input_files_;
24822494

24832495
// Specification of defaults to use for feature resolution. This defaults to
24842496
// just the global and C++ features, but can be overridden for other runtimes.

src/google/protobuf/descriptor_unittest.cc

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3898,7 +3898,7 @@ TEST(CustomOptions, UnusedImportError) {
38983898
&file_proto);
38993899
ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
39003900

3901-
pool.AddUnusedImportTrackFile("custom_options_import.proto", true);
3901+
pool.AddDirectInputFile("custom_options_import.proto", true);
39023902
ASSERT_TRUE(TextFormat::ParseFromString(
39033903
"name: \"custom_options_import.proto\" "
39043904
"package: \"protobuf_unittest\" "
@@ -6330,22 +6330,22 @@ TEST_F(ValidationErrorTest, AllowEnumAlias) {
63306330
}
63316331

63326332
TEST_F(ValidationErrorTest, UnusedImportWarning) {
6333-
pool_.AddUnusedImportTrackFile("bar.proto");
6333+
pool_.AddDirectInputFile("bar.proto");
63346334
BuildFile(
63356335
"name: \"bar.proto\" "
63366336
"message_type { name: \"Bar\" }");
63376337

6338-
pool_.AddUnusedImportTrackFile("base.proto");
6338+
pool_.AddDirectInputFile("base.proto");
63396339
BuildFile(
63406340
"name: \"base.proto\" "
63416341
"message_type { name: \"Base\" }");
63426342

6343-
pool_.AddUnusedImportTrackFile("baz.proto");
6343+
pool_.AddDirectInputFile("baz.proto");
63446344
BuildFile(
63456345
"name: \"baz.proto\" "
63466346
"message_type { name: \"Baz\" }");
63476347

6348-
pool_.AddUnusedImportTrackFile("public.proto");
6348+
pool_.AddDirectInputFile("public.proto");
63496349
BuildFile(
63506350
"name: \"public.proto\" "
63516351
"dependency: \"bar.proto\""
@@ -6360,7 +6360,7 @@ TEST_F(ValidationErrorTest, UnusedImportWarning) {
63606360
// optional Base base = 1;
63616361
// }
63626362
//
6363-
pool_.AddUnusedImportTrackFile("forward.proto");
6363+
pool_.AddDirectInputFile("forward.proto");
63646364
BuildFileWithWarnings(
63656365
"name: \"forward.proto\""
63666366
"dependency: \"base.proto\""
@@ -6391,7 +6391,7 @@ TEST_F(ValidationErrorTest, SamePackageUnusedImportError) {
63916391
message_type { name: "Bar" }
63926392
)pb");
63936393

6394-
pool_.AddUnusedImportTrackFile("import.proto", true);
6394+
pool_.AddDirectInputFile("import.proto", true);
63956395
BuildFileWithErrors(R"pb(
63966396
name: "import.proto"
63976397
package: "protobuf_unittest"
@@ -7344,7 +7344,7 @@ TEST_F(ValidationErrorTest, UnusedImportWithOtherError) {
73447344
" name: 'Bar'"
73457345
"}");
73467346

7347-
pool_.AddUnusedImportTrackFile("foo.proto", true);
7347+
pool_.AddDirectInputFile("foo.proto", true);
73487348
BuildFileWithErrors(
73497349
"name: 'foo.proto' "
73507350
"dependency: 'bar.proto' "
@@ -10866,6 +10866,7 @@ TEST_F(FeaturesTest, InvalidGroupLabel) {
1086610866
}
1086710867

1086810868
TEST_F(FeaturesTest, DeprecatedFeature) {
10869+
pool_.AddDirectInputFile("foo.proto");
1086910870
BuildDescriptorMessagesInTestPool();
1087010871
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());
1087110872
BuildFileWithWarnings(
@@ -10875,8 +10876,11 @@ TEST_F(FeaturesTest, DeprecatedFeature) {
1087510876
edition: EDITION_2023
1087610877
dependency: "google/protobuf/unittest_features.proto"
1087710878
options {
10878-
features {
10879-
[pb.test] { removed_feature: VALUE9 }
10879+
uninterpreted_option {
10880+
name { name_part: "features" is_extension: false }
10881+
name { name_part: "pb.test" is_extension: true }
10882+
name { name_part: "removed_feature" is_extension: false }
10883+
identifier_value: "VALUE9"
1088010884
}
1088110885
}
1088210886
)pb",
@@ -10890,6 +10894,68 @@ TEST_F(FeaturesTest, DeprecatedFeature) {
1089010894
pb::VALUE9);
1089110895
}
1089210896

10897+
TEST_F(FeaturesTest, IgnoreDeprecatedFeature) {
10898+
BuildDescriptorMessagesInTestPool();
10899+
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());
10900+
BuildFileWithWarnings(
10901+
R"pb(
10902+
name: "foo.proto"
10903+
syntax: "editions"
10904+
edition: EDITION_2023
10905+
dependency: "google/protobuf/unittest_features.proto"
10906+
options {
10907+
uninterpreted_option {
10908+
name { name_part: "features" is_extension: false }
10909+
name { name_part: "pb.test" is_extension: true }
10910+
name { name_part: "removed_feature" is_extension: false }
10911+
identifier_value: "VALUE9"
10912+
}
10913+
}
10914+
)pb",
10915+
"");
10916+
}
10917+
10918+
TEST_F(FeaturesTest, IgnoreTransitiveFeature) {
10919+
pool_.AddDirectInputFile("bar.proto");
10920+
BuildDescriptorMessagesInTestPool();
10921+
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());
10922+
BuildFileWithWarnings(
10923+
R"pb(
10924+
name: "foo.proto"
10925+
syntax: "editions"
10926+
edition: EDITION_2023
10927+
dependency: "google/protobuf/unittest_features.proto"
10928+
options {
10929+
uninterpreted_option {
10930+
name { name_part: "features" is_extension: false }
10931+
name { name_part: "pb.test" is_extension: true }
10932+
name { name_part: "removed_feature" is_extension: false }
10933+
identifier_value: "VALUE9"
10934+
}
10935+
}
10936+
message_type { name: "Foo" }
10937+
)pb",
10938+
"");
10939+
BuildFileWithWarnings(
10940+
R"pb(
10941+
name: "bar.proto"
10942+
syntax: "editions"
10943+
edition: EDITION_2023
10944+
dependency: "foo.proto"
10945+
message_type {
10946+
name: "Bar"
10947+
field {
10948+
name: "bar"
10949+
number: 1
10950+
label: LABEL_OPTIONAL
10951+
type: TYPE_MESSAGE
10952+
type_name: ".Foo"
10953+
}
10954+
}
10955+
)pb",
10956+
"");
10957+
}
10958+
1089310959
TEST_F(FeaturesTest, RemovedFeature) {
1089410960
BuildDescriptorMessagesInTestPool();
1089510961
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());

src/google/protobuf/port_def.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3),
147147
// Owner: ckennelly@, mkruskal@
148148
#define PROTOBUF_FUTURE_REMOVE_CREATEMESSAGE 1
149149

150+
// Renames DescriptorPool::AddUnusedImportTrackFile
151+
// Owner: mkruskal@
152+
#define PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT 1
153+
150154
#endif
151155

152156
#ifdef PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE

0 commit comments

Comments
 (0)