-
Notifications
You must be signed in to change notification settings - Fork 51
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
Change templates to be a single template. #792
Change templates to be a single template. #792
Conversation
Codecov Report
@@ Coverage Diff @@
## master #792 +/- ##
=========================================
+ Coverage 10.46% 11.57% +1.1%
=========================================
Files 496 504 +8
Lines 12130 12299 +169
=========================================
+ Hits 1270 1423 +153
- Misses 10860 10876 +16
Continue to review full report at Codecov.
|
I'll go through the massive changelist to perform some spot checks, any guidance on what to expect would be great. Also, is the feature complete? Should this be in its own branch until the templates are fully functional? |
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 am now convinced that this change should not go against the master
branch. The feature is not complete and therefore it should go against a private branch were we can iterate freely. Please change the target of the PR.
I did not look at the templates themselves, there are waaay too many files to do an effective review there. We'll have to go one by one, generating the various combinations and looking at the generated code.
|
||
namespace GoogleCloudExtension.TemplateWizards | ||
{ | ||
|
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.
Empty line.
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.
{ | ||
/// <summary> | ||
/// Wizard for a project template. Delegates to GoogleProjecTemplateSelectorWizard | ||
/// in GoogleCloudExtension.dll. That class can not be used directly because |
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.
Could you ellaborate a bit about the issues? Open an issue in the github repo so we can track this issue and point to 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.
When I first tried to reference a wizard class in GoogleCloudExtension.dll from a vstemplate file, I got an error popup about being unable to reference a class from an MEF assembly (which GoogleCloudExtension.dll, containing the package, is).
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.
Please on an issue so we can come back to this again later and fix it, if you think that this can be eventually fixed.
{ | ||
var fromUri = new Uri(fromDirectory.EnsureEndSeparator().Replace('\\', '/')); | ||
var toUri = new Uri(toDirectory.EnsureEndSeparator().Replace('\\', '/')); | ||
return fromUri.MakeRelativeUri(toUri).ToString().Replace('/', Path.DirectorySeparatorChar); |
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.
You are only using Path.DirectorySeparatorChar
here, but not above, you should use it everywhere in this method to be consistent.
The documentation is not exactly clear on what the relative path from one directory to another means, I would suggest adding an example.
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 don't use it above, because I want to convert both types of directory separators to '/' so Uri
will treat them as expected. I use it here because I am converting back to the native format.
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.
Hmm... Perhaps a comment on what you are doing would make this code clearer to read. Also, our code for VS is mostly Windows specific (i.e. not portable) so we can always assume that \ will be the path separator.
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.
Added comments.
/// return false if it is null. | ||
/// Empty string is valid so it returns true. | ||
/// </summary> | ||
public static bool IsDigitsOnly(string text) => text != null && text.All(char.IsDigit); |
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.
Why is an empty string considered to be all digits? It should return false
since by definition it does not contain digits.
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.
Also not my code.
/// </summary> | ||
public static IEnumerable<string> SplitStringBySpaceOrQuote(string source) | ||
{ | ||
if (source == 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.
If the source is null
or empty then you should probably return an empty enumerable no?
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.
This is not a function I wrote. This is a file being move into a different assembly.
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.
Please open an issue so we can track fixing this code then.
{ | ||
get | ||
{ | ||
if (_isMvc) |
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.
Seems like this should be an enum instead of booleans, since the type of template is mutually exclusive.
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.
<ResourceDictionary Source="../../../Theming/ThemingResources.xaml"/> | ||
</ResourceDictionary.MergedDictionaries> | ||
<DataTemplate DataType="{x:Type local:FrameworkType}"> | ||
<TextBlock Text="{Binding Converter={utils:EnumDisplayNameConverter}}"/> |
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.
Too much magic, just have this in the view model, which is the class responsible for talking to the view. The enums should always be view agnostic, including not having the localized string attached to them.
|
||
string version = result.SelectedVersion.Version; | ||
string templatePath = Path.Combine( | ||
thisTemplateDirectory, "..", "..", "..", result.AppType, "1033", version, $"{version}.vstemplate"); |
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 applaud the effort, but the code is Windows specific. You can specify a format string that will create the right path without using this. Is ok to hard code the '' for file paths on Windows specific code.
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.
Changes this to use Path.DirectoryName
multiple times.
/// <inheritdoc/> | ||
public void RunFinished() | ||
{ | ||
throw new NotImplementedException("This wizard should delegate to another wizard and cancel itself."); |
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.
This tells me that this PR should go against a separate feature branch, not the master branch, as we should not be committing unfinished features there.
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.
This is not unfinished. This method should never be called.
|
||
namespace GoogleCloudExtension.Utils | ||
{ | ||
public class EnumDisplayNameConverter : MarkupExtension, IValueConverter |
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.
Please don't use this, enums should not have a localized display string associated with them.
/// <summary> | ||
/// The selected framework type. | ||
/// </summary> | ||
public FrameworkType SelectedFramework { get; } |
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'm now even more convinced that we should not have localized strings associated with the enums like this. We should have a small class that associates the enum with the localized string, including one with the default value if necessary.
public class TemplateChooserViewModel : ViewModelBase | ||
{ | ||
private string _gcpProjectId; | ||
private FrameworkType _selectedFramework = (FrameworkType)(-1); |
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.
You should instead define an enum value of None
(which should be set to 0 btw) to indicate that there's no framework selected. This is one of the reasons why having magic to associate strings with enums does not work.
Add Asp.Net Core 1.1 templates. Add unit tests. Enable ProjectTemplate.Tests with VS2017.
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.
Comments about over complicated XAML constructs.
Also, make sure that the .csproj are idiomatic. For the 2.0 case Microsoft made a big case of making it very very simple, we should follow suit and have the same idiomatic projects.
/// </summary> | ||
public enum AppType | ||
{ | ||
None, |
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.
Nit, have a small comment for each option, helps when using it in intellisense. They are self-explanatory I know, but it will help in the long run.
private string _gcpProjectId; | ||
private FrameworkType _selectedFramework = (FrameworkType)(-1); | ||
private FrameworkType _selectedFramework = FrameworkType.None; |
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.
Great, thank you! :)
@@ -71,11 +79,11 @@ | |||
<RadioButton | |||
GroupName="AppType" | |||
Content="{x:Static ext:Resources.WizardTemplateChooserMvcLabel}" | |||
IsChecked="{Binding IsMvc}"/> | |||
IsChecked="{Binding AppType, Converter={utils:RadioEnumConverter Target={x:Static local:AppType.Mvc}}}"/> |
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 have to ask, what is the advantage of this vs. what you had before? Since the set of choices is well known, and limited, why having the extra complexity that your solution adds? If we were to have 10s of choices I would agree, but we only have 2 choices, and I don't think that we will ever have more than 4. Having it hardcoded in the UI is perfectly valid.
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.
Changed this back to have IsMvc/IsWebApi properties on the ViewModel.
@@ -16,7 +16,15 @@ | |||
<ResourceDictionary Source="../../../Theming/ThemingResources.xaml"/> | |||
</ResourceDictionary.MergedDictionaries> | |||
<DataTemplate DataType="{x:Type local:FrameworkType}"> | |||
<TextBlock Text="{Binding Converter={utils:EnumDisplayNameConverter}}"/> | |||
<TextBlock x:Name="TextDisplay"/> |
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.
Wouldn't it be simpler to just have two entries under the ComboBox
with the two options? I'm sorry but this solution is waaay more complex than what it really needs to be. You can even use the Tag
property in the TextBlock to contain the value of the enum that you want and just add two TextBlock
instances.
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.
@@ -16,7 +16,10 @@ | |||
|
|||
<ItemGroup> | |||
<PackageReference Include="Google.Cloud.Diagnostics.AspNetCore" Version="1.0.0" /> | |||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> | |||
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" /> |
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.
Looking at a 2.0 project generated by dotnet, it is much much simpler, it collapses all of these packages into:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
We should make sure that the generated .csproj files are idiomatic.
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.
Change framework type enum combobox to use ComboBoxItems. Change ASP.NET Core 2.0 templates to use Microsoft.AspNetCore.All.
Move EnsureEndSeparator to PathUtils. Add unit tests.
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.
Really looking good, thank you for taking the feedback.
Create a single template with a version and type selection dialog.
This is a fix for issues #781 and #782.