XamlStyler
XamlStyler copied to clipboard
Project's reference to Settings.XamlStyler has less priority than solution
(This issue is remain of #160)
StylerPackage.GetConfigPathForItem() has the code which find the FullPath of "Settings.XamlStyler" ref in project.
- https://github.com/Xavalon/XamlStyler/blob/765510a3b6aa9345dbd8f0bbc5825214f4941c8f/XamlStyler3.Package/StylerPackage.cs#L211
But this config-file path has less priority than solution's config-file path.
Visual Studio has "Link File" feature, which references external files as a project item.
Let think about following solution structure:
- Root/
- Solution.sln
- Settings.XamlStyler (setting 1)
- Project1/
- Project1.csproj
- Project1.xaml
- Settings.XamlStyler (link to ../Settings/Settings.XamlStyler)
- Settings/
- Settings.XamlStyler (setting 2)
Project1.xaml should be formatted according to setting 2, but setting 1 is used currently.
Project1.xaml should be formatted according to setting 2, but setting 1 is used currently.
I would expect Project1.xaml, in this case, to be formatted via setting 1, since it is the the first configuration in up hierarchy. setting 2 is inside of a sub-directory. Am I missing something in your example?
IMO, detailed and explicitly specified setting should have higher priority.
In example case, (1) project setting is more detailed than solution, and (2) it is specified explicitly.
It seems design decision.
I have a similar issue.
My solution structure is as follows:
- Root
BuildSolution.slnSettings.XamlStyler(setting 1)
Project1Project1.csprojSettings.XamlStyler(setting 2)
Project2Project2.csproj
In this case, Project1 is formatted according to setting 2, which is what I expect. ✔️
Project2 is formatted according to XamlStyler default settings, but I would expect it to be formatted according to setting 1. ❌
It seems, setting 1 is not discovered at all.
The documentation explains that the settings file is searched also in the directory of the solution file: Alternatively, put your external configuration inside a "Settings.XamlStyler" file in any directory up through your solution directory and this configuration will take precedence.
I'm using Visual Studio 2019 (16.4.2) and XAML Styler 3.2.5.
@schlotter If there are two solutions both references Projects2 and each have different Settings.XamlStyler, Xaml files in Project2 will be re-formatted differently according to the active solution. It seems problematic.
Alternatively, put your external configuration inside a "Settings.XamlStyler" file in any directory up through your solution directory and this configuration will take precedence.
The documentation does not make it as clear as it could be here, so I added emphasis to draw attention to how it only looks up through folder hierarchy. In your example, the build directory is a sibling to Project2, so it would only look in root, where a configuration file does not exist.
related: #154 SearchToDriveRoot Feature
How about this priority rule ?
(Above has lower priority)
- Visual Studio
- Solution Directory (if Solution directory is not a ancestor of project directory) (this seems not provide a clear benefit. But when
SearchToDriveRootis false, this rule allows solution wide common setting even if project is outside the solution directory.) - Drive Root
- Directories ... (usually include Solution Directory)
- Project Directory
- Project's reference To Settings.XamlStyler (treats as same as setting in project directory)
- Directories ...
- File's Directory
- File.xaml
- File's Directory
- Project Directory
- Directories ... (usually include Solution Directory)
(Below has higher priority)
@schlotter If there are two solutions both references Projects2 and each have different Settings.XamlStyler, Xaml files in Project2 will be re-formatted differently according to the active solution. It seems problematic.
I agree, that is not optimal.
How about this priority rule ?
What you suggest looks good to me!
To double-check I understand it correctly, here is an example:
RootSettings.XamlStyler(setting 1)BuildSolution.slnSettings.XamlStyler(setting 2)
Project1Project1.csprojSettings.XamlStyler(setting 3)
Project2Project2.csproj
In this case, setting 1 has the highest priority. Setting 1 will be used by Project1.csproj and Project2.csproj.
Setting 2 has second highest priority and setting 3 has third highest priority.
Setting 2 and setting 3 will not be used, as setting 1 takes precedence.
This will work for well for me, as I will ensure there is only one Settings.XamlStyler somewhere close to the root of the repository which is to be used by all projects.
Thank you!
How about this priority rule?
@tmatz I agree with the hierarchy here, but I don't think @schlotter's interpretation is quite right. The "closest" configuration in the up-hierarchy should take precedence. That allows you to specify a default solution-wide configuration, while overriding it for specific projects or directories.
Complicating the example a bit more...
RootSettings.XamlStyler(setting 1)BuildSolution.slnSettings.XamlStyler(setting 2)
Project1MainPage1.xamlSettings.XamlStyler(setting 3)Project1Control.xaml
Project2MainPage2.xamlProject2Control.xmalSettings.XamlStyler(setting 4)
Project3MainPage3.xamlProject3Control.xmal
Setting 1 is not applied anywhere
Setting 2 applies to MainPage2.xaml, MainPage3.xaml, and Project3Contorl.xaml
Setting 3 applies to MainPage1.xaml and Project1Control.xaml
Setting 4 applies to Project2Control.xaml
If Setting 2 was removed, then Setting 1 would apply to MainPage2.xaml, MainPage3.xaml, and Project3Contorl.xaml.
If Setting 2, Setting 3, and Setting 4 were all removed, then Setting 1 would apply to all files.
@schlotter @grochocki My proposal is different from both of your interpretations.
As @grochocki says, the "closest" configuration in the up-hierarchy should take precedence. By this rule, configuration will be selected as following:
Root/Settings.XamlStyler(setting 1)Build/Solution.slnSettings.XamlStyler(setting 2)
Project1/Settings.XamlStyler(setting 3)MainPage1.xaml(uses setting 3)sub/Project1Control.xaml(uses setting 3)
Project2/MainPage2.xaml(uses setting 1)sub/Settings.XamlStyler(setting 4)Project2Control.xmal(uses setting 4)
Project3/MainPage3.xaml(uses setting 1)sub/Project3Control.xmal(uses setting 1)
In this example, the solution directory is not in a up-hierarchy of any .xaml file. And, there is setting 1 which is in up-hierarchy of all .xaml files. So setting 2 is never used.
This is current implementation if SearchToDriveRoot option is true(~~default~~ wrong. default is false).
@grochocki To obey your interpretation, priority of solution directory should be inserted between up-hierarchy of .xaml file. Could you describe where is the insertion point?
In this example, the solution directory is not in a up-hierarchy of any .xaml file. And, there is setting 1 which is in up-hierarchy of all .xaml files. So setting 2 is never used.
I am fine with this. IMHO, trying to include the solution directory, if it is not a direct ancestor in folder up-hierarchy, does not provide a clear benefit.
This is current implementation if
SearchToDriveRootoption is true(default).
If this is the case, then I think we can close this as by design. Admittedly, I do not have our mock solution hierarchy to actually test live. A documentation update would help clarify this behavior, though.
In this example, the solution directory is not in a up-hierarchy of any .xaml file. And, there is setting 1 which is in up-hierarchy of all .xaml files. So setting 2 is never used.
This is current implementation if
SearchToDriveRootoption is true(default).
I will try that again tomorrow. In my tests finding a setting like setting 1 did not work, but I recall Settings.XamlStyler was four or five levels up from the project files...
I think there was no way of immediately seeing exactly which Settings.XamlStyler was loaded, was it?
I think there was no way of immediately seeing exactly which Settings.XamlStyler was loaded, was it?
Unfortunately, not. I test this using exaggerated indent sizes for different configuration files so I can quickly tell which one is being applied (e.g., 2, 20, 40, etc.).
I will try that again tomorrow. In my tests finding a setting like setting 1 did not work, but I recall
Settings.XamlStylerwas four or five levels up from the project files...
Oh, maybe I misunderstand? I will try that tomorrow too. (It should be a new feature of 3.2001.0)
@grochocki
IMHO, trying to include the solution directory, if it is not a direct ancestor in folder up-hierarchy, does not provide a clear benefit.
I agree.
@grochocki Main theme of this issue is the priority of project's reference.
Main theme of this issue is the priority of project's reference.
Right -- I suppose the question is whether there is a clear benefit to supporting linked configurations or whether the guidance should be just include the file directly (or in up-hierarchy). While I understand it is possible, is there any clear benefit to the folder structure in your original issue submission (with the linked settings file)?
is there any clear benefit to the folder structure in your original issue submission (with the linked settings file)?
I have never used the linked settings file feature. But when I knew this feature, I think this is useful for a situation like following:
Solution/Settings.XamlStyler(setting 1 for default setting)Project1/Project2/- ...
Project9/Settings.XamlStyler(setting 2 for a group of some projects)
Project9.Sub1/Project9.Sub1.csproj(has linked settings file points to setting 2)
Project9.Sub2/Project9.Sub2.csproj(has linked settings file points to setting 2)
Setting 1 applies to most projects (Project1, Project2, ...).
Setting 2 applies to some exceptional projects (Project9, Project9.Sub1, and Project9.Sub2). This setting is also wanted to be shared for ease of maintainance.
But in the current implementation, settings 1 applies to Project9.Sub1 and Project9.Sub2.
Current priority rule is like this:
(Above has lower priority)
- Visual Studio
- Project's linked settings file
- Drive Root
- Directories ... (usually include Solution Directory)
- Project Directory
- Directories ...
- Xaml File's Directory
- Directories ...
- Project Directory
- Directories ... (usually include Solution Directory)
(Below has higher priority)
I had misunderstood until now. SearchToDriveRoot option is default false.
(Of course. this is a very big change)
When SearchToDriveRoot option is false, the configurations are selected as follows:
Root/Settings.XamlStyler(setting 1 not applied to anyone)Build/Solution.slnSettings.XamlStyler(setting 2 not applied to anyone)
Project1/Settings.XamlStyler(setting 3)MainPage1.xaml(uses setting 3)sub/Project1Control.xaml(uses setting 3)
Project2/MainPage2.xaml(uses vs option setting)sub/Settings.XamlStyler(setting 4)Project2Control.xmal(uses setting 4)
Project3/MainPage3.xaml(uses vs option setting)sub/Project3Control.xmal(uses vs option setting)
Project4/Project4.csproj(has linked settings file point to setting 5)MainPage4.xaml(uses setting 5)
Settings/Settings.XamlStyler(setting 5)
Both setting 1 and setting 2 are not applied to anyone. Since the project directory is outside the solution directory, configuration files are searched up to the project directory.
I think it should be possible to retrieve the solution directory (i.e., Build/). If so, even if SearchToDriveRoot is false, that would allow Setting 2 to be applied.
Alternatively, we could consider updating the SearchToDriveRoot default to true, but I was originally opposed to that, because it would mean that for anyone not using a configuration, we would always be crawling to root and turning up empty.
As a side note, one interesting behavior of the current implementation is that if the project and solution are on different drives, the configuration file will only be searched up to the project directory, even if the SearchToDriveRoot option is true.
I think it should be possible to retrieve the solution directory (i.e.,
Build/). If so, even ifSearchToDriveRootis false, that would allow Setting 2 to be applied.Alternatively, we could consider updating the
SearchToDriveRootdefault to true, but I was originally opposed to that, because it would mean that for anyone not using a configuration, we would always be crawling to root and turning up empty.
Arguments in favor of adding SearchToDriveRoot default to true:
.editorconfigis by default searched up to the rootReSharper.DotSettingsof ReSharper is by default searched up to the root
Searching by default up to the root is useful to ensure development teams (working with many solutions in different directories, but with a common repository and thus common repository root) use consistent settings.
At the moment, I can only ensure that by asking everyone to set SearchToDriveRoot to true (which never works) or by accepting that this does not work and placing Settings.XamlStyler in many locations all over the repo and keeping the files in sync.
Thus, I would prefer the simpler approach which is to set SearchToDriveRoot to true by default.
In this example, the solution directory is not in a up-hierarchy of any .xaml file. And, there is setting 1 which is in up-hierarchy of all .xaml files. So setting 2 is never used. This is current implementation if
SearchToDriveRootoption is true(default).I will try that again tomorrow. In my tests finding a setting like setting 1 did not work, but I recall
Settings.XamlStylerwas four or five levels up from the project files...
It was already confirmed above that SearchToDriveRoot is false by default. I have just verified that again with XamlStyler 3.2001.0.
As a side note, one interesting behavior of the current implementation is that if the project and solution are on different drives, the configuration file will only be searched up to the project directory, even if the SearchToDriveRoot option is true.
Hmm. This feels like an extreme edge case, though. Not sure it is worth optimizing for this scenario.
Arguments in favor of adding SearchToDriveRoot default to true...
Seems reasonable enough. I am fine with changing the default here to true assuming the behavior is as described in @tmatz's comment.