Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grpc.Tools: Parse warnings from libprotobuf (fix #27502) #30371

Merged
merged 2 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,21 @@ public void DirectorySlashTrimmingCases(string given, string expect)
"Import google/protobuf/empty.proto but not used.")]
[TestCase("../Protos/greet.proto(14) : error in column=10: \"name\" is already defined in \"Greet.HelloRequest\".", null, 0, 0, null)]
[TestCase("../Protos/greet.proto: Import \"google / protobuf / empty.proto\" was listed twice.", null, 0, 0, null)]
[TestCase("[libprotobuf WARNING T:\\altsrc\\github\\...\\csharp\\csharp_enum.cc:74] Duplicate enum value Work (originally Work) in PhoneType; adding underscore to distinguish",
"T:\\altsrc\\github\\...\\csharp\\csharp_enum.cc",
74, 0,
"Duplicate enum value Work (originally Work) in PhoneType; adding underscore to distinguish")]
[TestCase("[libprotobuf ERROR T:\\path\\...\\filename:23] Some message", null, 0, 0, null)]
[TestCase("[libprotobuf FATAL T:\\path\\...\\filename:23] Some message", null, 0, 0, null)]
public void WarningsParsed(string stderr, string file, int line, int col, string message)
{
_task.StdErrMessages.Add(stderr);

bool matched = false;
_mockEngine
.Setup(me => me.LogWarningEvent(It.IsAny<BuildWarningEventArgs>()))
.Callback((BuildWarningEventArgs e) => {
matched = true;
if (file != null)
{
Assert.AreEqual(file, e.File);
Expand All @@ -221,6 +229,14 @@ public void WarningsParsed(string stderr, string file, int line, int col, string

bool result = _task.Execute();
Assert.IsFalse(result);

// To get here in the test then either the event fired and the values matched
// or the event did not fire (input did not parse as a warning).
// If it did not parse as a warning then check that the expected message is null
if (!matched && message != null)
{
Assert.Fail($"Expected match: {message}");
}
}

[TestCase(
Expand All @@ -237,13 +253,21 @@ public void WarningsParsed(string stderr, string file, int line, int col, string
"Import \"google / protobuf / empty.proto\" was listed twice.")]
[TestCase("../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.", null, 0, 0, null)]
[TestCase("../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.", null, 0, 0, null)]
[TestCase("[libprotobuf WARNING T:\\altsrc\\github\\...\\csharp\\csharp_enum.cc:74] Duplicate enum value Work (originally Work) in PhoneType; adding underscore to distinguish",
null, 0, 0, null)]
[TestCase("[libprotobuf ERROR T:\\path\\...\\filename:23] Some message",
"T:\\path\\...\\filename", 23, 0, "ERROR Some message")]
[TestCase("[libprotobuf FATAL T:\\path\\...\\filename:23] Some message",
"T:\\path\\...\\filename", 23, 0, "FATAL Some message")]
public void ErrorsParsed(string stderr, string file, int line, int col, string message)
{
_task.StdErrMessages.Add(stderr);

bool matched = false;
_mockEngine
.Setup(me => me.LogErrorEvent(It.IsAny<BuildErrorEventArgs>()))
.Callback((BuildErrorEventArgs e) => {
matched = true;
if (file != null)
{
Assert.AreEqual(file, e.File);
Expand All @@ -262,8 +286,17 @@ public void ErrorsParsed(string stderr, string file, int line, int col, string m
}
});


bool result = _task.Execute();
Assert.IsFalse(result);

// To get here in the test then either the event fired and the values matched
// or the event did not fire (input did not parse as an error).
// If it did not parse as an error then check that the expected message is null
if (!matched && message != null)
{
Assert.Fail($"Expected match: {message}");
}
}
};
}
57 changes: 57 additions & 0 deletions src/csharp/Grpc.Tools/ProtoCompile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,63 @@ public class ProtoCompile : ToolTask
}
},

// Example warning from plugins that use GOOGLE_LOG
// [libprotobuf WARNING T:\altsrc\..\csharp_enum.cc:74] Duplicate enum value Work (originally Work) in PhoneType; adding underscore to distinguish
new ErrorListFilter
{
Pattern = new Regex(
pattern: "^\\[.+? WARNING (?'FILENAME'.+?):(?'LINE'\\d+?)\\] ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
// The filename and line logged by the plugins may not be useful to the
// end user as they are not the location in the proto file but rather
// in the source code for the plugin. Log them anyway as they may help in
// diagnostics.
int.TryParse(match.Groups["LINE"].Value, out var line);
log.LogWarning(
subcategory: null,
warningCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: line,
columnNumber: 0,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["TEXT"].Value);
}
},

// Example error from plugins that use GOOGLE_LOG
// [libprotobuf ERROR T:\path\...\filename:23] Some message
// [libprotobuf FATAL T:\path\...\filename:23] Some message
new ErrorListFilter
{
Pattern = new Regex(
pattern: "^\\[.+? (?'LEVEL'ERROR|FATAL) (?'FILENAME'.+?):(?'LINE'\\d+?)\\] ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
// The filename and line logged by the plugins may not be useful to the
// end user as they are not the location in the proto file but rather
// in the source code for the plugin. Log them anyway as they may help in
// diagnostics.
int.TryParse(match.Groups["LINE"].Value, out var line);
log.LogError(
subcategory: null,
errorCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: line,
columnNumber: 0,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["LEVEL"].Value + " " + match.Groups["TEXT"].Value);
}
},

// Example error without location
//../Protos/greet.proto: Import "google/protobuf/empty.proto" was listed twice.
new ErrorListFilter
Expand Down