[Code quality] Standardize settings file paths using Path.Combine (#49164) - #49474
[Code quality] Standardize settings file paths using Path.Combine (#49164)#49474raza-khan0108 wants to merge 3 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Thanks for picking this up. I see var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);And also _directory.CreateDirectory(System.IO.Path.Combine(Helper.LocalApplicationDataFolder(), "Microsoft", "PowerToys", powertoy)); |
|
Good question! A few reasons why keeping
|
|
Oh I see 👍 Fair points. |
Jay-o-Way
left a comment
There was a problem hiding this comment.
I suppose the constant SettingsFile isn't really needed either, if it's only used in one line of code. Other than that - LGTM.
|
I've removed the single-use |
There was a problem hiding this comment.
A few comments about this approach, file-by-file and then with some general comments at the end:
SettingPath.cs
The move from interpolated backslash strings to discrete Path.Combine() segments is reasonable, but the same construction - "Microsoft" + "PowerToys" + "{x}" is used in multiple places. I'd suggest extracting this to a private helper to keep the root path defined in one place, e.g.:
private string GetModuleFolderPath(string powertoy) =>
string.IsNullOrWhiteSpace(powertoy)
? _path.Combine(Helper.LocalApplicationDataFolder(), "Microsoft", "PowerToys")
: _path.Combine(Helper.LocalApplicationDataFolder(), "Microsoft", "PowerToys", powertoy);This also fixes a pre-existing issue where 3 of the 4 path constructions do not use _path, but instead call System.IO.Path.Combine() directly. _path abstracts away the file system so it can be mocked and tested in the unit tests.
If we're doing a refactor here, it makes sense to correct this.
Utilities.Helper
Helper.UserLocalAppDataPath is a mutable static property and LocalApplicationDataFolder() is intentionally a method rather than a cached field precisely because it can change during the process runtime - this is because the MouseWithoutBorders service can override the AppData folder:
PowerToys/src/modules/MouseWithoutBorders/App/Class/Program.cs
Lines 127 to 133 in fc680d3
It would be useful to add a comment to this effect in the Utilities.Helper code, as it's not immediately obvious that the local AppData folder is mutable for a reason.
LanguageModel.cs
Here, Environment.GetFolderPath() is still called directly:
We should use the Helper.LocalApplicationDataFolder() helper which exists precisely because Environment.GetFolderPath() is not always correct. AFAIK, LanguageModel doesn't run in the context of MouseWithoutBorder's service, so there's no practical impact of this change currently, but it should still use the right API for consistency and because it's in the same library as Helper already.
LanguageHelper.cs
This cannot be updated to have a dependency on Settings.UI.Library because it would create a circular dependency. The update to use Path.Combine() is cosmetic only - the real problem is the direct call to Environment.GetFolderPath(), which remains. This needs to be tracked as a separate architectural issue.
SettingsFilePath field
You have removed SettingsFilePath in LanguageModel and LanguageHelper. Both this and SettingsFile are public consts. I'm pretty sure these aren't referenced elsewhere - GeneralViewModel uses LanguageModel as a data object for its ObservableCollection but doesn't use those constants directly - but it would be good to double-check and state this in the description.
General
Callers outside of the Settings project (so in FolderUtils.cs, EnvironmentVariablesService.cs and UpdatingSettings.cs) should be routing through SettingsUtils.GetSettingsFilePath()and not constructing their own paths in any form. GetSettingsFilePath() is specifically designed for this purpose.
Testing
You checked the "Tests: Added/updated and all pass" checkbox in the description, but there aren't any new or updated tests in your PR. I don't think it's enough to assert that you've manually checked things on such a fundamental change. For a refactor touching SettingPath specifically - a class with IDirectory/IPath abstractions that exist precisely for testability - I think it would be reasonable to expect new tests covering the changed methods, or which existing test methods were run and how they provide adequate coverage for the update. "Paths are correct" is not self-evident, especially for the three methods which didn't use _path - using a mock filesystem would let us check that directly.
…ttingPath unit tests
|
I've updated the PR with the following changes:
|
Summary of the Pull Request
This PR addresses issue #49164 by refactoring manual, inconsistent, and error-prone string concatenations of settings file paths across C# modules to use
Path.Combineand clean path segments.PR Checklist
Detailed Description of the Pull Request / Additional comments
src/common/ManagedCommon/LanguageHelper.cs: Replaced manual string concatenation (localAppDataDir + SettingsFilePath + SettingsFile) withPath.Combine(localAppDataDir, "Microsoft", "PowerToys", SettingsFile). Removed unused slash-paddedSettingsFilePathconstant.src/settings-ui/Settings.UI.Library/LanguageModel.cs: Replaced manual string concatenation withPath.Combine(localAppDataDir, "Microsoft", "PowerToys", SettingsFile).src/settings-ui/Settings.UI.Library/UpdatingSettings.cs: Replaced manual string concatenation withPath.Combine(localAppDataDir, "Microsoft", "PowerToys", SettingsFile).src/settings-ui/Settings.UI.Library/SettingPath.cs: Replaced hardcoded string slashes ($"Microsoft\\PowerToys\\{powertoy}") with multi-segmentPath.Combinecalls inSettingsFolderExists,CreateSettingsFolder,DeleteSettings, andGetSettingsPath.src/modules/Workspaces/WorkspacesCsharpLibrary/Utils/FolderUtils.cs: Replaced string concatenation inDataFolder()withPath.Combine.src/modules/EnvironmentVariables/EnvironmentVariablesUILib/Helpers/EnvironmentVariablesService.cs: Updated_profilesJsonFilePathinitialization to use structuredPath.Combinesegments. Cleaned up unusedProfilesJsonFileSubPathconstant.Validation Steps Performed
Path.CombineacrossManagedCommon,Settings.UI.Library,Workspaces, andEnvironmentVariables.