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

Project properties simplification #136

Merged

Conversation

andrew-boyarshin
Copy link
Collaborator

@andrew-boyarshin andrew-boyarshin commented Jul 16, 2018

  • Import and adapt parts of Microsoft.Build.Evaluation for precise Condition attribute parsing [MIT]
  • Create ConditionEvaluator to glue Project2015To2017 and MSBuild expression trees
  • Add sophisticated simplification routine to ProjectPropertiesReader to reduce duplication of defaults (handling variety of cases, including non-default project-wide property override and default conditionalpropertygroup-wide override)
  • ProjectPropertiesReader: replace hacky configuration list retrieval routine with a better one using ConditionEvaluator
  • Add Project.Platforms list property retrieval to match Project.Configurations
  • [breaking change] Real support for multiple TargetFrameworks (Project.TargetFrameworks: IReadOnlyList -> IList, now always non-null, set accessor removed)
  • Do not write default values of $(Configurations) and $(Platforms) in ProjectWriter
  • Update tests to reflect changes (e.g. changed type of Project.TargetFrameworks)
  • Create a number of tests to showcase and verify simplification behavior

@andrew-boyarshin
Copy link
Collaborator Author

andrew-boyarshin commented Jul 16, 2018

Progress for issue #113

@andrew-boyarshin
Copy link
Collaborator Author

I have reimplemented ConditionEvaluator and some simplification parts.
I use simplified Microsoft.Build.Evaluation sources (MIT, yay!) to provide perfect Condition property parsing (matching real MSBuild of course). It can also provide proper condition evaluation for possible future needs. Shunting-Yard and RPN stack evaluator are no longer needed (it is far outmatched by real expression parsing).
I have also improved property simplification routine, targeting code clarity and handling additional cases.
I expect the code to be ready for review in 1 day. I am going to separate everything in multiple PRs this time to simplify reviewing.

@andrew-boyarshin andrew-boyarshin changed the title Property simplification + use MSBuild.Sdks.Extras for WPF & WinForms Project properties simplification Jul 23, 2018
@@ -596,5 +793,15 @@ public class ProjectPropertiesReadTest

return project;
}

internal static bool ValidateChildren(IEnumerable<XElement> value, params string[] expected)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally internal. Used in another PR's tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it is used in this PR (XamlTransformationTest).

@andrew-boyarshin
Copy link
Collaborator Author

andrew-boyarshin commented Jul 23, 2018

@hvanbakel @mungojam All 3 PRs are ready to be reviewed and merged. They can work separately, order of merging is not fixed (although natural is #136 -> #138 -> #139).

@hvanbakel
Copy link
Owner

hvanbakel commented Jul 23, 2018 via email


static internal bool IsHexAlphabetic(char candidate)
{
return (candidate == 'a' || candidate == 'b' || candidate == 'c' || candidate == 'd' || candidate == 'e' || candidate == 'f' ||
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (candidate >= 97 && candidate <= 102) || (candidate >= 65 && candidate <= 70)
would work too and is probably a lot faster

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that's MSBuild. :) I really don't think we should bring in our own modifications except those to reduce dependencies on MSBuild code. We might later want to update code from upstream so such changes might introduce confusion.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, can we include a link to the source somewhere here in case things get outdated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have introduced upstream.md in *Reading* directory.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the answer is no, but would https://github.com/daveaglick/Buildalyzer be of any use here to avoid copying the code in? It would be a bit too hefty a dependency probably and may not actually help. Or are git sub-modules another possibility to directly bring in the code from MS Build? I've never actually used them before.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mungojam unfortunately, we cannot bring in the code directly. It requires removal of specific code, non-trivial replacements in a couple of places so that there are no dependencies introduced. And since we don't want our code to bring in the whole enormous dependency on MSBuild and its dependencies and .NET Core SDK and Microsoft SDKs and NuGet, Buildalyzer (that does exactly the thing) can be of no use to us.

public IReadOnlyList<XElement> OtherPropertyGroups { get; set; }

public IReadOnlyList<string> TargetFrameworks { get; set; }
public IList<string> TargetFrameworks { get; } = new List<string>();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be mutable, right? You read it once and from that point on it's immutable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I do add new items there. First, it is used in ProjectReader in 2nd PR. then, it is used in ProjectPropertiesReader for TargetFrameworkVersion. I believe mutability is nothing compared to how comparatively ugly things would be with constructing new colection, preserving old ones and adding new.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean, I didn't see that change in this PR, that's where my comment came from. Looking at your other PR it makes sense.

{
#region MSBuild Conditional routine

private static readonly Lazy<Regex> SinglePropertyRegex = new Lazy<Regex>(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cost of initializing this is not worth the Lazy construct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSBuild code again (probably to make no-op actions faster). But this is indeed sth I could change. Will do.

@hvanbakel
Copy link
Owner

Looks good in general, a few comments I don't know if you want to update your PR to reflect those or if you want me to fix those when I merge it down?

I'll also be doing a few style changes (I very much dislike if blocks without braces) but that's taste.

@hvanbakel
Copy link
Owner

Now that the other one is merged you should be able to simplify https://github.com/hvanbakel/CsprojToVs2017/blob/master/Project2015To2017/Reading/ProjectReader.cs?#L104

@andrew-boyarshin
Copy link
Collaborator Author

OK, I am working on this PR (expected timeframe — 4 hours). Will also rebase on latest HEAD. I will also include XamlTransformationTest since 2nd PR is merged now.

* Import and adapt parts of Microsoft.Build.Evaluation for precise Condition attribute parsing [MIT]
* Create ConditionEvaluator to glue Project2015To2017 and MSBuild expression trees
* Add sophisticated simplification routine to ProjectPropertiesReader
* ProjectPropertiesReader: replace hacky configuration list retrieval routine with a better one using ConditionEvaluator
* Add Project.Platforms list property retrieval to match Project.Configurations
* Real support for multiple TargetFrameworks (Project.TargetFrameworks: IReadOnlyList<T> -> IList<T>)
* Do not write default values of $(Configurations) and $(Platforms) in ProjectWriter
* Update tests to reflect changes (e.g. changed type of Project.TargetFrameworks)
* Create a number of tests to showcase and verify simplification behavior
@andrew-boyarshin
Copy link
Collaborator Author

andrew-boyarshin commented Jul 25, 2018

@hvanbakel done! Also added upstream.md to highlight the essentials of MSBuild code import.

}

// Default configuration-specific paths
// todo: move duplicated paths from conditional groups to non-conditional one
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a serious matter for different PR. I have a good idea how to implement this one though.

@andrew-boyarshin
Copy link
Collaborator Author

Forgot to enable conditional block in ProjectReader you've mentioned. Will do in next PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants