-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Implement ability for project properties to suppress and elevate warnings #1928
Conversation
FYI @jaredpar |
Nice! |
@@ -1079,6 +1080,10 @@ private void SetProjectCurrentDirectory() | |||
|
|||
_projectLoggingContext = _nodeLoggingContext.LogProjectStarted(_requestEntry); | |||
|
|||
// Now that the project has started, parse a few known properties which indicate warning codes to treat as errors or messages | |||
// | |||
ConfigureWarningsAsErrorsAndMessages(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully this is the only place where MSBuild evaluates a project file during build. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you foresee any performance degradation by adding this call? I assumed it was safe since the project has "started" building...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It runs once for each project evaluation, so it should scale linearly with number of evaluations (Project nr x (msbuild tasks per project)). I think ~5000 projects is considered "outlier big".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offline discussion: My bad, this actually happens only once per node.
|
||
// Ensure everything that is required is available at this time | ||
// | ||
if (project != null && buildEventContext != null && loggingService != null && buildEventContext.ProjectInstanceId != BuildEventContext.InvalidProjectInstanceId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check this works on a p2p node as well. Nodes initially assign a temp project ID (maybe the invalid one?) and I don't remember whether they get the global ID before or after they evaluate the project.
} | ||
else | ||
{ | ||
ISet<string> warningsAsErrors = ParseWarningCodes(project.GetPropertyValue(MSBuildConstants.WarningsAsErrors)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the user defines TreatWarningsAsErrors=True and also WarningsAsErrors="a;b;c;d"? I'd expect msbuild to treat only the specified warnings as errors, as opposed to ignoring the warning list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment, MSBuildTreatWarningsAsErrors
will override any list. This is the same way that argument works for the compilers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, didn't know. Go with the same behaviour as the compilers then. Except for the warning list separator :)
} | ||
|
||
return new HashSet<string>( | ||
warnings.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd only keep semicolons, as they are the msbuild approved way of separating things. And then maybe use ExpressionShredder.SplitSemiColonSeparatedList
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
public void AddWarningsAsMessages(int projectInstanceId, ISet<string> codes) | ||
{ | ||
lock (_lockObject) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are using a concurrent dictionary, rather than locking, you can use a thread safe Lazy to initialize it, and then not use the external lock when using it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this out but hit a snag. I'm using the state of null
as an indicator if any warnings should be treated as an error/message. If I use a Lazy<T>
, then I would have to expose it as such so that the caller can determine if HasValue
is true
. Leaving it the way it is, the property remains of type IDictionary
and a simple null check is done. If its okay to have IBuildEventSink
have a property that is of type Lazy<T>
, then I'll do it.
} | ||
} | ||
|
||
ISet<string> warningsAsMessages = ParseWarningCodes(project.GetPropertyValue(MSBuildConstants.WarningsAsMessages)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the user has the same warning code as both a message and an error? I'd expect error to win, on the grounds that errors are more serious than messages. Or maybe emit a warning saying that both were specified and the intent is ambiguous. The user can then treat that new warning as a message (but hopefully not as an error as well) :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suppressing a warning overrides elevating one. This is so you can treat all warnings as errors but still turn a few of them off.
{ | ||
// This only applies if the user specified /warnaserror from the command-line or added an empty set through the object model | ||
// | ||
if (WarningsAsErrors != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rename WarningsAsErrors/Messages to something like GlobalWarningsAsErrors/Messages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name is technically part of our public API already as a property to BuildParameters
. I could rename the internal property on EventSourceSink
if you feel strongly about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was more of a nit. Thought it's worth making it clear in the ILoggingService that WarningsAsErrors
is the global, master switch and not the local per project one.
…ings. Introduce MSBuildTreatWarningsAsErrors property that when set to true will treat all warnings as errors when building a project. Introduce MSBuildWarningsAsErrors property which is a semicolon delmited list of warning codes to treat as errors when building a project. Introduce MSBuildWarningsAsMessages property which is a semicolon delimited list of warning codes to treat as low importance messages. This allows users to control warnings at the project level via standard MSBuild properties. They can be set in a project, an import, or from the command-line. The limitation here is that the warnings can only include ones that occur during a build. This is because the properties are not read until after parsing so warnings generated during parse/evaluation happen too soon. For these warnings, users will only be able to treat them as errors/messages with the /WarnAsError and /WarnAsMessage command-line arguments. Closes dotnet#1886
Should reduce memory use when building large project trees
Introduce
MSBuildTreatWarningsAsErrors
property that when set to true will treat all warnings as errors when building a project.Introduce
MSBuildWarningsAsErrors
property which is a semicolon delmited list of warning codes to treat as errors when building a project.Introduce
MSBuildWarningsAsMessages
property which is a semicolon delimited list of warning codes to treat as low importance messages.This allows users to control warnings at the project level via standard MSBuild properties. They can be set in a project, an import, or from the command-line.
The limitation here is that the warnings can only include ones that occur during a build. This is because the properties are not read until after parsing so warnings generated during parse/evaluation happen too soon. For these warnings, users will only be able to treat them as errors/messages with the
/WarnAsError
and/WarnAsMessage
command-line arguments.Closes #1886