Skip to content

Commit cafeaa4

Browse files
Have the protoc CLI properly report any parser warnings.
Remove the naming warnings that would be considered noisy if they were suddenly enabled with no easy way to disable the warnings. The upcoming Edition 2024 naming style enforcement feature and a planned corresponding change to the linter which respects NOLINT comments will cover the cases that these warnings would. The parser appears to have been accidentally silently suppressed on the CLI path all along; while they were reachable on other usages of the parser, those cases are secondary compared to what we consider the main entry point and so no longer having the naming warnings on those should not locally be a major loss. PiperOrigin-RevId: 716223703
1 parent 94ae26d commit cafeaa4

File tree

6 files changed

+95
-154
lines changed

6 files changed

+95
-154
lines changed

src/google/protobuf/compiler/command_line_interface_tester.cc

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void CommandLineInterfaceTester::RunProtocWithArgs(
8080

8181
return_code_ = cli_.Run(static_cast<int>(args.size()), argv.data());
8282

83-
error_text_ = GetCapturedTestStderr();
83+
captured_stderr_ = GetCapturedTestStderr();
8484
#if !defined(__CYGWIN__)
8585
captured_stdout_ = GetCapturedTestStdout();
8686
#endif
@@ -116,33 +116,42 @@ void CommandLineInterfaceTester::CreateTempDir(absl::string_view name) {
116116

117117
void CommandLineInterfaceTester::ExpectNoErrors() {
118118
EXPECT_EQ(0, return_code_);
119-
EXPECT_EQ("", error_text_);
119+
120+
// Note: since warnings and errors are both simply printed to stderr, we
121+
// can't holistically distinguish them here; in practice we don't have
122+
// multiline warnings so just counting any line with 'warning:' in it
123+
// is sufficient to separate warnings and errors in practice.
124+
for (const auto& line :
125+
absl::StrSplit(captured_stderr_, '\n', absl::SkipEmpty())) {
126+
EXPECT_THAT(line, HasSubstr("warning:"));
127+
}
120128
}
121129

122130
void CommandLineInterfaceTester::ExpectErrorText(
123131
absl::string_view expected_text) {
124132
EXPECT_NE(0, return_code_);
125-
EXPECT_THAT(error_text_, HasSubstr(absl::StrReplaceAll(
126-
expected_text, {{"$tmpdir", temp_directory_}})));
133+
EXPECT_THAT(captured_stderr_,
134+
HasSubstr(absl::StrReplaceAll(expected_text,
135+
{{"$tmpdir", temp_directory_}})));
127136
}
128137

129138
void CommandLineInterfaceTester::ExpectErrorSubstring(
130139
absl::string_view expected_substring) {
131140
EXPECT_NE(0, return_code_);
132-
EXPECT_THAT(error_text_, HasSubstr(expected_substring));
141+
EXPECT_THAT(captured_stderr_, HasSubstr(expected_substring));
133142
}
134143

135144
void CommandLineInterfaceTester::ExpectWarningSubstring(
136145
absl::string_view expected_substring) {
137146
EXPECT_EQ(0, return_code_);
138-
EXPECT_THAT(error_text_, HasSubstr(expected_substring));
147+
EXPECT_THAT(captured_stderr_, HasSubstr(expected_substring));
139148
}
140149

141150
#if defined(_WIN32) && !defined(__CYGWIN__)
142151
bool CommandLineInterfaceTester::HasAlternateErrorSubstring(
143152
const std::string& expected_substring) {
144153
EXPECT_NE(0, return_code_);
145-
return error_text_.find(expected_substring) != std::string::npos;
154+
return captured_stderr_.find(expected_substring) != std::string::npos;
146155
}
147156
#endif // _WIN32 && !__CYGWIN__
148157

@@ -162,7 +171,7 @@ void CommandLineInterfaceTester::
162171
ExpectCapturedStderrSubstringWithZeroReturnCode(
163172
absl::string_view expected_substring) {
164173
EXPECT_EQ(0, return_code_);
165-
EXPECT_THAT(error_text_, HasSubstr(expected_substring));
174+
EXPECT_THAT(captured_stderr_, HasSubstr(expected_substring));
166175
}
167176

168177
void CommandLineInterfaceTester::ExpectFileContent(absl::string_view filename,

src/google/protobuf/compiler/command_line_interface_tester.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,8 @@ class CommandLineInterfaceTester : public testing::Test {
136136
// The result of Run().
137137
int return_code_;
138138

139-
// The captured stderr output.
140-
std::string error_text_;
139+
std::string captured_stderr_;
141140

142-
// The captured stdout.
143141
std::string captured_stdout_;
144142

145143
std::vector<std::unique_ptr<CodeGenerator>> generators_;

src/google/protobuf/compiler/command_line_interface_unittest.cc

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <gmock/gmock.h>
2020
#include "absl/log/absl_check.h"
2121
#include "absl/strings/escaping.h"
22+
#include "absl/strings/match.h"
2223
#include "absl/strings/str_cat.h"
2324
#include "absl/types/span.h"
2425
#include "google/protobuf/compiler/command_line_interface_tester.h"
@@ -4022,6 +4023,20 @@ TEST_F(CommandLineInterfaceTest,
40224023
"extendee message foo.Foo");
40234024
}
40244025

4026+
TEST_F(CommandLineInterfaceTest, WarningForReservedNameNotIdentifier) {
4027+
CreateTempFile("foo.proto", R"schema(
4028+
syntax = "proto2";
4029+
package foo;
4030+
message Foo {
4031+
reserved "not ident";
4032+
})schema");
4033+
4034+
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir foo.proto");
4035+
ExpectNoErrors();
4036+
ExpectWarningSubstring(
4037+
"Reserved name \"not ident\" is not a valid identifier.");
4038+
}
4039+
40254040
TEST_F(CommandLineInterfaceTest,
40264041
ExtensionDeclarationVerificationDeclarationUndeclaredError) {
40274042
CreateTempFile("foo.proto", R"schema(
@@ -4236,6 +4251,19 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
42364251
captured_stdout_ = GetCapturedTestStdout();
42374252
captured_stderr_ = GetCapturedTestStderr();
42384253

4254+
// Note: since warnings and errors are both simply printed to stderr, we
4255+
// can't holistically distinguish them here; in practice we don't have
4256+
// multiline warnings so just counting any line with 'warning:' in it
4257+
// is sufficient to separate warnings and errors in practice.
4258+
for (const auto& line :
4259+
absl::StrSplit(StripCR(captured_stderr_), '\n', absl::SkipEmpty())) {
4260+
if (absl::StrContains(line, "warning:")) {
4261+
captured_warnings_.push_back(std::string(line));
4262+
} else {
4263+
captured_errors_.push_back(std::string(line));
4264+
}
4265+
}
4266+
42394267
return result == 0;
42404268
}
42414269

@@ -4257,6 +4285,30 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
42574285
ExpectStdoutMatchesText(expected_output);
42584286
}
42594287

4288+
void ExpectNoErrors() { EXPECT_THAT(captured_errors_, testing::IsEmpty()); }
4289+
4290+
void ExpectNoWarnings() {
4291+
EXPECT_THAT(captured_warnings_, testing::IsEmpty());
4292+
}
4293+
4294+
void ExpectError(absl::string_view expected_text) {
4295+
EXPECT_THAT(captured_errors_, testing::Contains(expected_text));
4296+
}
4297+
4298+
void ExpectErrorSubstring(absl::string_view expected_substring) {
4299+
EXPECT_THAT(captured_errors_,
4300+
testing::Contains(testing::HasSubstr(expected_substring)));
4301+
}
4302+
4303+
void ExpectWarning(absl::string_view expected_text) {
4304+
EXPECT_THAT(captured_warnings_, testing::Contains(expected_text));
4305+
}
4306+
4307+
void ExpectWarningSubstring(absl::string_view expected_substring) {
4308+
EXPECT_THAT(captured_warnings_,
4309+
testing::Contains(testing::HasSubstr(expected_substring)));
4310+
}
4311+
42604312
void ExpectStdoutMatchesText(const std::string& expected_text) {
42614313
EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_));
42624314
}
@@ -4295,6 +4347,9 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
42954347
int duped_stdin_;
42964348
std::string captured_stdout_;
42974349
std::string captured_stderr_;
4350+
std::vector<std::string> captured_warnings_;
4351+
std::vector<std::string> captured_errors_;
4352+
42984353
std::string unittest_proto_descriptor_set_filename_;
42994354
};
43004355

@@ -4318,7 +4373,7 @@ TEST_P(EncodeDecodeTest, Encode) {
43184373
EXPECT_TRUE(
43194374
Run(absl::StrCat(args, " --encode=protobuf_unittest.TestAllTypes")));
43204375
ExpectStdoutMatchesBinaryFile(golden_path);
4321-
ExpectStderrMatchesText("");
4376+
ExpectNoErrors();
43224377
}
43234378

43244379
TEST_P(EncodeDecodeTest, Decode) {
@@ -4331,7 +4386,7 @@ TEST_P(EncodeDecodeTest, Decode) {
43314386
ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath(
43324387
"google/protobuf/"
43334388
"testdata/text_format_unittest_data_oneof_implemented.txt"));
4334-
ExpectStderrMatchesText("");
4389+
ExpectNoErrors();
43354390
}
43364391

43374392
TEST_P(EncodeDecodeTest, Partial) {
@@ -4340,8 +4395,7 @@ TEST_P(EncodeDecodeTest, Partial) {
43404395
Run("google/protobuf/unittest.proto"
43414396
" --encode=protobuf_unittest.TestRequired"));
43424397
ExpectStdoutMatchesText("");
4343-
ExpectStderrMatchesText(
4344-
"warning: Input message is missing required fields: a, b, c\n");
4398+
ExpectWarning("warning: Input message is missing required fields: a, b, c");
43454399
}
43464400

43474401
TEST_P(EncodeDecodeTest, DecodeRaw) {
@@ -4356,24 +4410,25 @@ TEST_P(EncodeDecodeTest, DecodeRaw) {
43564410
ExpectStdoutMatchesText(
43574411
"1: 123\n"
43584412
"14: \"foo\"\n");
4359-
ExpectStderrMatchesText("");
4413+
ExpectNoErrors();
43604414
}
43614415

43624416
TEST_P(EncodeDecodeTest, UnknownType) {
43634417
EXPECT_FALSE(
43644418
Run("google/protobuf/unittest.proto"
43654419
" --encode=NoSuchType"));
43664420
ExpectStdoutMatchesText("");
4367-
ExpectStderrMatchesText("Type not defined: NoSuchType\n");
4421+
ExpectError("Type not defined: NoSuchType");
43684422
}
43694423

43704424
TEST_P(EncodeDecodeTest, ProtoParseError) {
43714425
EXPECT_FALSE(
43724426
Run("net/proto2/internal/no_such_file.proto "
43734427
"--encode=NoSuchType"));
43744428
ExpectStdoutMatchesText("");
4375-
ExpectStderrContainsText(
4376-
"net/proto2/internal/no_such_file.proto: No such file or directory\n");
4429+
ExpectErrorSubstring(
4430+
"net/proto2/internal/no_such_file.proto: "
4431+
"No such file or directory");
43774432
}
43784433

43794434
TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) {
@@ -4389,7 +4444,7 @@ TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) {
43894444
EXPECT_TRUE(Run(absl::StrCat(
43904445
args, " --encode=protobuf_unittest.TestAllTypes --deterministic_output")));
43914446
ExpectStdoutMatchesBinaryFile(golden_path);
4392-
ExpectStderrMatchesText("");
4447+
ExpectNoErrors();
43934448
}
43944449

43954450
TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) {
@@ -4399,8 +4454,7 @@ TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) {
43994454
EXPECT_FALSE(
44004455
Run("google/protobuf/unittest.proto"
44014456
" --decode=protobuf_unittest.TestAllTypes --deterministic_output"));
4402-
ExpectStderrMatchesText(
4403-
"Can only use --deterministic_output with --encode.\n");
4457+
ExpectError("Can only use --deterministic_output with --encode.");
44044458
}
44054459

44064460
INSTANTIATE_TEST_SUITE_P(FileDescriptorSetSource, EncodeDecodeTest,

src/google/protobuf/compiler/importer.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector
9494
had_errors_ = true;
9595
}
9696

97+
void RecordWarning(int line, int column, absl::string_view message) override {
98+
if (multi_file_error_collector_ != nullptr) {
99+
multi_file_error_collector_->RecordWarning(filename_, line, column,
100+
message);
101+
}
102+
}
103+
97104
private:
98105
std::string filename_;
99106
MultiFileErrorCollector* multi_file_error_collector_;

0 commit comments

Comments
 (0)