{"$schema":"https://json.schemastore.org/sarif-2.1.0.json","version":"2.1.0","runs":[{"tool":{"driver":{"name":"codehealth","informationUri":"https://codehealth.canine.dev","rules":[{"id":"D1","name":"Cyclomatic Complexity","shortDescription":{"text":"Cyclomatic Complexity"},"helpUri":"https://codehealth.canine.dev/dimensions/D1"},{"id":"D2","name":"Cognitive Complexity","shortDescription":{"text":"Cognitive Complexity"},"helpUri":"https://codehealth.canine.dev/dimensions/D2"},{"id":"D3","name":"God Classes","shortDescription":{"text":"God Classes"},"helpUri":"https://codehealth.canine.dev/dimensions/D3"},{"id":"D4","name":"Code Duplication","shortDescription":{"text":"Code Duplication"},"helpUri":"https://codehealth.canine.dev/dimensions/D4"},{"id":"D5","name":"Coupling","shortDescription":{"text":"Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D5"},{"id":"D6","name":"Cohesion (LCOM4)","shortDescription":{"text":"Cohesion (LCOM4)"},"helpUri":"https://codehealth.canine.dev/dimensions/D6"},{"id":"D9","name":"Test Distribution","shortDescription":{"text":"Test Distribution"},"helpUri":"https://codehealth.canine.dev/dimensions/D9"},{"id":"D10","name":"Test Quality","shortDescription":{"text":"Test Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D10"},{"id":"D11","name":"Test Reliability","shortDescription":{"text":"Test Reliability"},"helpUri":"https://codehealth.canine.dev/dimensions/D11"},{"id":"D12","name":"Dependency Hygiene","shortDescription":{"text":"Dependency Hygiene"},"helpUri":"https://codehealth.canine.dev/dimensions/D12"},{"id":"D13","name":"Secret Scanning","shortDescription":{"text":"Secret Scanning"},"helpUri":"https://codehealth.canine.dev/dimensions/D13","relationships":[{"target":{"id":"CWE-798","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-259","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-798","CWE-259"]}},{"id":"D15","name":"Churn \u00D7 Complexity Hotspots","shortDescription":{"text":"Churn \u00D7 Complexity Hotspots"},"helpUri":"https://codehealth.canine.dev/dimensions/D15"},{"id":"D16","name":"Bus Factor","shortDescription":{"text":"Bus Factor"},"helpUri":"https://codehealth.canine.dev/dimensions/D16"},{"id":"D17","name":"Explicit Debt","shortDescription":{"text":"Explicit Debt"},"helpUri":"https://codehealth.canine.dev/dimensions/D17"},{"id":"D18","name":"Solution Shape","shortDescription":{"text":"Solution Shape"},"helpUri":"https://codehealth.canine.dev/dimensions/D18"},{"id":"D19","name":"Documentation Quality","shortDescription":{"text":"Documentation Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D19"},{"id":"D20","name":"ADR Quality","shortDescription":{"text":"ADR Quality"},"helpUri":"https://codehealth.canine.dev/dimensions/D20"},{"id":"D21","name":"Naming Consistency","shortDescription":{"text":"Naming Consistency"},"helpUri":"https://codehealth.canine.dev/dimensions/D21"},{"id":"D23","name":"Boundary Type-Coupling","shortDescription":{"text":"Boundary Type-Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D23"},{"id":"D24","name":"Comment Value","shortDescription":{"text":"Comment Value"},"helpUri":"https://codehealth.canine.dev/dimensions/D24"},{"id":"D26","name":"Project Cohesion","shortDescription":{"text":"Project Cohesion"},"helpUri":"https://codehealth.canine.dev/dimensions/D26"},{"id":"D28","name":"Secrets (history)","shortDescription":{"text":"Secrets (history)"},"helpUri":"https://codehealth.canine.dev/dimensions/D28","relationships":[{"target":{"id":"CWE-798","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-259","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-798","CWE-259"]}},{"id":"D29","name":"Static Analysis (SAST)","shortDescription":{"text":"Static Analysis (SAST)"},"helpUri":"https://codehealth.canine.dev/dimensions/D29","relationships":[{"target":{"id":"CWE-79","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-89","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-78","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-94","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]},{"target":{"id":"CWE-77","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}},"kinds":["relevant"]}],"properties":{"cwe":["CWE-79","CWE-89","CWE-78","CWE-94","CWE-77"]}},{"id":"D34","name":"Knowledge Freshness","shortDescription":{"text":"Knowledge Freshness"},"helpUri":"https://codehealth.canine.dev/dimensions/D34"},{"id":"D35","name":"Change Coupling","shortDescription":{"text":"Change Coupling"},"helpUri":"https://codehealth.canine.dev/dimensions/D35"}]}},"results":[{"ruleId":"D1","level":"warning","message":{"text":"MetadataDownloader.DownloadMetadataAsync (cyclomatic 112): MetadataDownloader.DownloadMetadataAsync has cyclomatic complexity 112 (threshold 15). Most of this is not in the body itself: 1 of the 112 points is its own statement and the rest belongs to one function literal inside it that branches (line 318). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Metadata/MetadataDownloader.cs"},"region":{"startLine":311}}}],"partialFingerprints":{"codehealthFindingId/v1":"5966c9d18a18f7325a4c384f990c098927dc584d033f7948adc9f6a1d7c6f4de"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.EditingGame_PropertyChanged (cyclomatic 90): GameEditViewModel.EditingGame_PropertyChanged has cyclomatic complexity 90 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelFieldChecks.cs"},"region":{"startLine":849}}}],"partialFingerprints":{"codehealthFindingId/v1":"843ce48eeda7f6610f46330f615d8c8b128164f0777c21f09462af909ab70ab2"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.ConfirmDialog (cyclomatic 84): GameEditViewModel.ConfirmDialog has cyclomatic complexity 84 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":525}}}],"partialFingerprints":{"codehealthFindingId/v1":"0ff880b83209320e9e7be59fd694297eb8905ef3dc95b7ecd549e71c5f1d401f"}},{"ruleId":"D1","level":"warning","message":{"text":"GameDatabase.MigrateNewDatabaseFormat (cyclomatic 74): GameDatabase.MigrateNewDatabaseFormat has cyclomatic complexity 74 (threshold 15). Of this number, 55 points are the body\u0027s own statements and 19 belong to 5 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabaseMigration.cs"},"region":{"startLine":22}}}],"partialFingerprints":{"codehealthFindingId/v1":"f822eadfd3643bf53916311d19c2d1b7a29c0dc071d5ad0dcf243c0f2a92f3be"}},{"ruleId":"D1","level":"warning","message":{"text":"Game.GetDifferences (cyclomatic 65): Game.GetDifferences has cyclomatic complexity 65 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":2032}}}],"partialFingerprints":{"codehealthFindingId/v1":"ed4597ac45831bb2157a6c29371627950940394f5585ea1e2193d4b2841f0f31"}},{"ruleId":"D1","level":"warning","message":{"text":"TGA.LoadFunc (cyclomatic 57): TGA.LoadFunc has cyclomatic complexity 57 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5298}}}],"partialFingerprints":{"codehealthFindingId/v1":"fd26483ab63c8397e6c338406e72c19018150e9e7bb9f2f5a53fef6cf0344198"}},{"ruleId":"D1","level":"warning","message":{"text":"Game.CopyDiffTo (cyclomatic 55): Game.CopyDiffTo has cyclomatic complexity 55 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1750}}}],"partialFingerprints":{"codehealthFindingId/v1":"8122fa7118c839e9164f1d877129835a95871a355a291e11fbfe2353a52ba3d7"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteApplication.PlayniteApplication.ctor (cyclomatic 54): PlayniteApplication.PlayniteApplication.ctor has cyclomatic complexity 54 (threshold 15). Of this number, 52 points are the body\u0027s own statements and 2 belong to 2 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"74e527580fcac4e83f3ab827eaaa6e32bc7f69e4ed247d962e82ea1b0847d1a0"}},{"ruleId":"D1","level":"warning","message":{"text":"GameScanner.ScanDirectoryBase (cyclomatic 51): GameScanner.ScanDirectoryBase has cyclomatic complexity 51 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":693}}}],"partialFingerprints":{"codehealthFindingId/v1":"e13a20ad03844b69db54f59bde1153258f0b408be701e69e08503354dd826862"}},{"ruleId":"D1","level":"warning","message":{"text":"TGA.ToBitmapFunc (cyclomatic 48): TGA.ToBitmapFunc has cyclomatic complexity 48 (threshold 15). To reduce it, separate the branches: extract each independent case into its own named function, or replace a long branch ladder over a single value with a data-driven lookup or dispatch table."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5681}}}],"partialFingerprints":{"codehealthFindingId/v1":"951653ce21c7b55c938b8601a194a9128155062a7345b6b8abec1ee2bd358799"}},{"ruleId":"D1","level":"warning","message":{"text":"FullscreenAppViewModel.InitializeCommands (cyclomatic 47): FullscreenAppViewModel.InitializeCommands has cyclomatic complexity 47 (threshold 15). Most of this is not in the body itself: 1 of the 47 points is its own statement and the rest belongs to 12 function literals inside it that branch (lines 100, 56, 205, \u2026). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals\u0027 work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs"},"region":{"startLine":45}}}],"partialFingerprints":{"codehealthFindingId/v1":"386a025981c415dd2d36622591fc9f7d6a2f201bc19035695cc636b787b07d2f"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.GetDisplayDiffFields (cyclomatic 46): GameEditViewModel.GetDisplayDiffFields has cyclomatic complexity 46 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":56}}}],"partialFingerprints":{"codehealthFindingId/v1":"50f4ab6fcc56d9f2372231100b5d04c4f6ad5a1975254e8fda1109462c159242"}},{"ruleId":"D1","level":"warning","message":{"text":"DatabaseExplorer.LoadValues (cyclomatic 43): DatabaseExplorer.LoadValues has cyclomatic complexity 43 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":723}}}],"partialFingerprints":{"codehealthFindingId/v1":"cd6272fe2c3392c18cf31d0a303c547e47de9c616f3dbbe0f7dd3c659ea55328"}},{"ruleId":"D1","level":"warning","message":{"text":"TGA.CheckAndUpdateOffsets (cyclomatic 42): TGA.CheckAndUpdateOffsets has cyclomatic complexity 42 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":4799}}}],"partialFingerprints":{"codehealthFindingId/v1":"80585f58c1078e42f2cea70c67cfc6e81ecf9d5eedb396556cfd0fcd6bd62278"}},{"ruleId":"D1","level":"warning","message":{"text":"MetadataDownloader.ProcessField (cyclomatic 38): MetadataDownloader.ProcessField has cyclomatic complexity 38 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Metadata/MetadataDownloader.cs"},"region":{"startLine":136}}}],"partialFingerprints":{"codehealthFindingId/v1":"b4b23095a00f4444cd2e9708659adc0e9fd4503025feb309f8b48f22016c92d6"}},{"ruleId":"D1","level":"warning","message":{"text":"DesktopCollectionView.SetViewDescriptions (cyclomatic 37): DesktopCollectionView.SetViewDescriptions has cyclomatic complexity 37 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopCollectionView.cs"},"region":{"startLine":187}}}],"partialFingerprints":{"codehealthFindingId/v1":"82d3124d0a6e5d33ad291c20bab5fd7ec4064bb9dae57c00d3674a6adef8d56a"}},{"ruleId":"D1","level":"warning","message":{"text":"GameDatabase.ImportGames (cyclomatic 35): GameDatabase.ImportGames has cyclomatic complexity 35 (threshold 15). Of this number, 34 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":1205}}}],"partialFingerprints":{"codehealthFindingId/v1":"4aea19d7cff66c6ab99a83a403997aa8621bbc6fed389734554d2977da98c332"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesEditor.PlayGame (cyclomatic 35): GamesEditor.PlayGame has cyclomatic complexity 35 (threshold 15). Of this number, 34 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":189}}}],"partialFingerprints":{"codehealthFindingId/v1":"36b045daf6defa2fb421cb1d95c188a40f5ec97223f7490d57427811cbf340a8"}},{"ruleId":"D1","level":"warning","message":{"text":"GameScanner.Scan (cyclomatic 32): GameScanner.Scan has cyclomatic complexity 32 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":185}}}],"partialFingerprints":{"codehealthFindingId/v1":"81fb3e624b070469d9c1db473b01d6a7680dc9289500eed3398e099d54d2d64d"}},{"ruleId":"D1","level":"warning","message":{"text":"FilterSettings.ClearFilters (cyclomatic 32): FilterSettings.ClearFilters has cyclomatic complexity 32 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":956}}}],"partialFingerprints":{"codehealthFindingId/v1":"bfdcace3c0601b37d3ddad3ac312372524874e687aa323498905e5295989ca8e"}},{"ruleId":"D1","level":"warning","message":{"text":"DatabaseExplorer.ApplyFilter (cyclomatic 31): DatabaseExplorer.ApplyFilter has cyclomatic complexity 31 (threshold 15). To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Where every arm is uniform \u2014 the same kind of value, with no behaviour of its own \u2014 a table keyed by the case is the shorter form; wherever the arms carry different data or different behaviour, keep them as cases, because collapsing those trades an explicit, reviewable set of cases for nothing."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":592}}}],"partialFingerprints":{"codehealthFindingId/v1":"d60040731147fe99eee3fbfeeda14b860aec7ada870b2fca4b5adf7c86f39c37"}},{"ruleId":"D1","level":"warning","message":{"text":"FilterSettings.ApplyFilter (cyclomatic 31): FilterSettings.ApplyFilter has cyclomatic complexity 31 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":1221}}}],"partialFingerprints":{"codehealthFindingId/v1":"dd9f63fc8ada089e8cc54a44fe5c9dfcd6fc8cce72c8211fc4fb02af0dcd12e0"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesGridView.GetColumn (cyclomatic 31): GamesGridView.GetColumn has cyclomatic complexity 31 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs"},"region":{"startLine":208}}}],"partialFingerprints":{"codehealthFindingId/v1":"f85ae869025fab8605b0fa05d54b8aa900a5c9ae0dd2757306703a562d2e3907"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesEditor.Controllers_Stopped (cyclomatic 30): GamesEditor.Controllers_Stopped has cyclomatic complexity 30 (threshold 15). Of this number, 23 points are the body\u0027s own statements and 7 belong to 2 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1416}}}],"partialFingerprints":{"codehealthFindingId/v1":"70deaa865ddf1d74708b70ec7e2879faed2fb0e692d73dc64c351cc983223117"}},{"ruleId":"D1","level":"warning","message":{"text":"GameTools.GetMultiGameEditObject (cyclomatic 30): GameTools.GetMultiGameEditObject has cyclomatic complexity 30 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GameTools.cs"},"region":{"startLine":28}}}],"partialFingerprints":{"codehealthFindingId/v1":"6551eb97f3ff99c2d2256eec68a3a8037ab1adbcb7fc06e70fab7112b2bb46bf"}},{"ruleId":"D1","level":"warning","message":{"text":"FilterMatcher.Match (cyclomatic 29): FilterMatcher.Match has cyclomatic complexity 29 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase_Filters.cs"},"region":{"startLine":60}}}],"partialFingerprints":{"codehealthFindingId/v1":"f81c9b5d6fc9568d4655b1e788338384c94dba623dcf28133bb79ab07c8428f9"}},{"ruleId":"D1","level":"warning","message":{"text":"MetadataComparisonViewModel.ConfirmDialog (cyclomatic 29): MetadataComparisonViewModel.ConfirmDialog has cyclomatic complexity 29 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs"},"region":{"startLine":264}}}],"partialFingerprints":{"codehealthFindingId/v1":"fabfbf43c146259f40931086917efcafc2c7068d8d71ca83486e7aeb0039377f"}},{"ruleId":"D1","level":"warning","message":{"text":"Backup.BackupData (cyclomatic 28): Backup.BackupData has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Backup.cs"},"region":{"startLine":73}}}],"partialFingerprints":{"codehealthFindingId/v1":"c051b5806984c7e384204ed2e21f6a6af1aa51a8bac0378fcfd1edd5904d2869"}},{"ruleId":"D1","level":"warning","message":{"text":"MenuItems.GetSearchGameMenuItems (cyclomatic 28): MenuItems.GetSearchGameMenuItems has cyclomatic complexity 28 (threshold 15). Of this number, 27 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuItems.cs"},"region":{"startLine":164}}}],"partialFingerprints":{"codehealthFindingId/v1":"9aecd3af12f6c0ca9910e2b4ebe435c0a29521a0bfea1a2518fff443931557bd"}},{"ruleId":"D1","level":"warning","message":{"text":"TGA.LoadFunc (cyclomatic 28): TGA.LoadFunc has cyclomatic complexity 28 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5138}}}],"partialFingerprints":{"codehealthFindingId/v1":"456c4315d5f4c57f879a98c423e756ea125cf25216547733c3e38c11865754a1"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteApplication.Application_Startup (cyclomatic 27): PlayniteApplication.Application_Startup has cyclomatic complexity 27 (threshold 15). Of this number, 25 points are the body\u0027s own statements and 2 belong to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":599}}}],"partialFingerprints":{"codehealthFindingId/v1":"352fe06c0b0c9ccca6fac08ccae9997ed6c51432da9031d48cbddeb53d24760e"}},{"ruleId":"D1","level":"warning","message":{"text":"CloneObject.CopyProperties (cyclomatic 26): CloneObject.CopyProperties has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/CloneObject.cs"},"region":{"startLine":113}}}],"partialFingerprints":{"codehealthFindingId/v1":"38018d45073fbda5008da3527c9b2e943320b701ef4cd6198cb01f4caf3ea59c"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.LoadNewMetadata (cyclomatic 26): GameEditViewModel.LoadNewMetadata has cyclomatic complexity 26 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":252}}}],"partialFingerprints":{"codehealthFindingId/v1":"9b86c10510964aceed0e0a43e569ed6f12ff9c9295278ffb52b385c0617ed1fc"}},{"ruleId":"D1","level":"warning","message":{"text":"ItemsControlEx.ItemsControlEx_PreviewKeyDown (cyclomatic 26): ItemsControlEx.ItemsControlEx_PreviewKeyDown has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs"},"region":{"startLine":38}}}],"partialFingerprints":{"codehealthFindingId/v1":"b479e2e9a768d846d12fc3b9174d1944d4e9a6f447cf0cea81f5d85d4636bc85"}},{"ruleId":"D1","level":"warning","message":{"text":"Main.OnApplyTemplate (cyclomatic 26): Main.OnApplyTemplate has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/Views/Main.cs"},"region":{"startLine":226}}}],"partialFingerprints":{"codehealthFindingId/v1":"ab83ae61a454672c48caceac07c049844383231a4c09819d7d85de85bf31e105"}},{"ruleId":"D1","level":"warning","message":{"text":"FullscreenAppViewModel.Fullscreen_PropertyChanged (cyclomatic 26): FullscreenAppViewModel.Fullscreen_PropertyChanged has cyclomatic complexity 26 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":579}}}],"partialFingerprints":{"codehealthFindingId/v1":"a9aeb833310f09ff7e5433e6cc9cb3419f2f0ecff22ae9e17a70ca5b0dbcc872"}},{"ruleId":"D1","level":"warning","message":{"text":"Backup.RestoreBackup (cyclomatic 25): Backup.RestoreBackup has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Backup.cs"},"region":{"startLine":212}}}],"partialFingerprints":{"codehealthFindingId/v1":"beb58688241d3d6305c298c0ddc672a4da7e2cf5d3ea570f167b9c2172b2fd7c"}},{"ruleId":"D1","level":"warning","message":{"text":"DatabaseFilter.UpdateAllCollections (cyclomatic 25): DatabaseFilter.UpdateAllCollections has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseFilter.cs"},"region":{"startLine":375}}}],"partialFingerprints":{"codehealthFindingId/v1":"4e79528505ab1012c8672a24ad9013aa49a859c5579c2a476511c65499626bbe"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesEditor.CalculateGameSize (cyclomatic 25): GamesEditor.CalculateGameSize has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":566}}}],"partialFingerprints":{"codehealthFindingId/v1":"10c62dd0f7e8825c1048f2b3a0870d1f2b07200a3288549bbe4f4988269cbc99"}},{"ruleId":"D1","level":"warning","message":{"text":"ImageSourceManager.GetImage (cyclomatic 25): ImageSourceManager.GetImage has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ImageSourceManager.cs"},"region":{"startLine":160}}}],"partialFingerprints":{"codehealthFindingId/v1":"7e2b6fd811dcf6788be4176a1d118f3365cedf348ab2462aab95481aad0f39f9"}},{"ruleId":"D1","level":"warning","message":{"text":"GenericPlayController.Start (cyclomatic 25): GenericPlayController.Start has cyclomatic complexity 25 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":481}}}],"partialFingerprints":{"codehealthFindingId/v1":"d70724f7ceaa7482aa0869a7bfb07e316619db6b87cb5bc8f80226211461372e"}},{"ruleId":"D1","level":"warning","message":{"text":"BitmapExtensions.BitmapFromStream (cyclomatic 24): BitmapExtensions.BitmapFromStream has cyclomatic complexity 24 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/BitmapExtensions.cs"},"region":{"startLine":249}}}],"partialFingerprints":{"codehealthFindingId/v1":"0c4f757090ef256b2a179c8dd85996efacb35913c8d8cad7da26976bb7f5a280"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteApplication.PipeService_CommandExecuted (cyclomatic 23): PlayniteApplication.PipeService_CommandExecuted has cyclomatic complexity 23 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":780}}}],"partialFingerprints":{"codehealthFindingId/v1":"ebe3a868dde5ebacd58b3d5e809805f3e6eaa08f71a55888315ba522d866fc6b"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteSettings.LoadSettings (cyclomatic 22): PlayniteSettings.LoadSettings has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":2352}}}],"partialFingerprints":{"codehealthFindingId/v1":"66aa5634be2af91f37d4e9d612d0ffdba7e9a4ac2805c4e096224a2ce0a2ae94"}},{"ruleId":"D1","level":"warning","message":{"text":"ThemeManager.ApplyTheme (cyclomatic 22): ThemeManager.ApplyTheme has cyclomatic complexity 22 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Themes.cs"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"182795539184fd2bca8fc8b8b266b82d2184cd7c6388d006efa93b4f5a2aaa26"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteApplication.CurrentDomain_UnhandledException (cyclomatic 21): PlayniteApplication.CurrentDomain_UnhandledException has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":496}}}],"partialFingerprints":{"codehealthFindingId/v1":"d20726542f59c88ad9485e2bb642359d1a26b96ed49c7343f285d8339c540019"}},{"ruleId":"D1","level":"warning","message":{"text":"TGA.SaveFunc (cyclomatic 21): TGA.SaveFunc has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5517}}}],"partialFingerprints":{"codehealthFindingId/v1":"016eeb7a9bf4b0da0963830e03c2e7eb8e2cacac56af97585ddc042a7031a62b"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesCollectionViewEntry.GetAdvancedGroupedEntry (cyclomatic 21): GamesCollectionViewEntry.GetAdvancedGroupedEntry has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesCollectionViewEntry.cs"},"region":{"startLine":273}}}],"partialFingerprints":{"codehealthFindingId/v1":"0bbf32b51b33bba8064ba7be684b9cf11fb5f3932861145146f9fe694e21495e"}},{"ruleId":"D1","level":"warning","message":{"text":"GamesEditor.GetPlayActions (cyclomatic 21): GamesEditor.GetPlayActions has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1682}}}],"partialFingerprints":{"codehealthFindingId/v1":"a71c9f2ea33006eec52039ff9d76bf0ca3532203cc14d8209b027c3efb383b68"}},{"ruleId":"D1","level":"warning","message":{"text":"StatisticsViewModel.FillData (cyclomatic 21): StatisticsViewModel.FillData has cyclomatic complexity 21 (threshold 15). Of this number, 18 points are the body\u0027s own statements and 3 belong to 2 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/StatisticsViewModel.cs"},"region":{"startLine":325}}}],"partialFingerprints":{"codehealthFindingId/v1":"7618700399e97580b017679fa29b09d12fe9889a79220ea5ad72510cc3372f58"}},{"ruleId":"D1","level":"warning","message":{"text":"ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor (cyclomatic 21): ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor has cyclomatic complexity 21 (threshold 15). Of this number, 20 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/ExtensionsMenuViewModels.cs"},"region":{"startLine":222}}}],"partialFingerprints":{"codehealthFindingId/v1":"e535985db78181c2039feaf1fefedb9879f9854299462e304576eb3fe047280a"}},{"ruleId":"D1","level":"warning","message":{"text":"DatParser.ParseProperty (cyclomatic 21): DatParser.ParseProperty has cyclomatic complexity 21 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Utilities/DatParser.cs"},"region":{"startLine":129}}}],"partialFingerprints":{"codehealthFindingId/v1":"deb60d83ee0d29dfb679e8d65156d41fc0ce8d4951d0b6d78560f22b5776ca17"}},{"ruleId":"D1","level":"warning","message":{"text":"BsonReader.ReadElement (cyclomatic 20): BsonReader.ReadElement has cyclomatic complexity 20 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs"},"region":{"startLine":80}}}],"partialFingerprints":{"codehealthFindingId/v1":"485324c9b28c0d82fd5c84da90fdbc5805ff6fcf3dbfe4fd3d40895e16535af1"}},{"ruleId":"D1","level":"warning","message":{"text":"Game.GetScoreGroup (cyclomatic 20): Game.GetScoreGroup has cyclomatic complexity 20 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1597}}}],"partialFingerprints":{"codehealthFindingId/v1":"a1c1f0e428e9cd31e15f9ef597aa8dff1dafebae1db7f236352d4d63d9bbfb39"}},{"ruleId":"D1","level":"warning","message":{"text":"GameMenu.InitializeItems (cyclomatic 20): GameMenu.InitializeItems has cyclomatic complexity 20 (threshold 15). Of this number, 19 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs"},"region":{"startLine":105}}}],"partialFingerprints":{"codehealthFindingId/v1":"68258307fb0b707c668421391b8a64089803e1e825caecacd5e94a2ed7e24f6f"}},{"ruleId":"D1","level":"warning","message":{"text":"EmulatedGamesImportViewModel.StartScan (cyclomatic 20): EmulatedGamesImportViewModel.StartScan has cyclomatic complexity 20 (threshold 15). Of this number, 15 points are the body\u0027s own statements and 5 belong to 4 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatedGamesImportViewModel.cs"},"region":{"startLine":331}}}],"partialFingerprints":{"codehealthFindingId/v1":"a1b39d624727bb023015ac639a5bdfc449f0865daafb28178de46909a16c5207"}},{"ruleId":"D1","level":"warning","message":{"text":"SettingsViewModel.ConfirmDialog (cyclomatic 20): SettingsViewModel.ConfirmDialog has cyclomatic complexity 20 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/SettingsViewModel.cs"},"region":{"startLine":525}}}],"partialFingerprints":{"codehealthFindingId/v1":"3555f7d2a142838032d8ce9b5efe863608a78381f4f6ff5f5932bbe324e6ab8b"}},{"ruleId":"D1","level":"warning","message":{"text":"FadeImage.LoadNewSource (cyclomatic 19): FadeImage.LoadNewSource has cyclomatic complexity 19 (threshold 15). Of this number, 17 points are the body\u0027s own statements and 2 belong to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controls/FadeImage.xaml.cs"},"region":{"startLine":259}}}],"partialFingerprints":{"codehealthFindingId/v1":"9f8857929de8a2b1424aaceababf937bcde182c1207d8dc717fe5f6071137033"}},{"ruleId":"D1","level":"warning","message":{"text":"SearchViewModel.TextBoxKeyUp (cyclomatic 19): SearchViewModel.TextBoxKeyUp has cyclomatic complexity 19 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":883}}}],"partialFingerprints":{"codehealthFindingId/v1":"90b8b345aef16b9a234a086b9d51a9af45b277be98a5c2032b8fe40ec2e37b99"}},{"ruleId":"D1","level":"warning","message":{"text":"GenericPlayController.StartEmulator (cyclomatic 18): GenericPlayController.StartEmulator has cyclomatic complexity 18 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"1c22c331b0e7d6de7839c758b6b323b6e8fc520dbc87b1af6fc99725074dd1b1"}},{"ruleId":"D1","level":"warning","message":{"text":"Programs.GetUWPApps (cyclomatic 17): Programs.GetUWPApps has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Programs2.cs"},"region":{"startLine":294}}}],"partialFingerprints":{"codehealthFindingId/v1":"13a766005c24a895e251c36cbe03a95b14b82ccda271f19c48ce0ce1c5a1e537"}},{"ruleId":"D1","level":"warning","message":{"text":"SdkHelpers.ResolveUiItemIcon (cyclomatic 17): SdkHelpers.ResolveUiItemIcon has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SdkHelpers.cs"},"region":{"startLine":23}}}],"partialFingerprints":{"codehealthFindingId/v1":"caca3a44efb78474187d796f04b1d53f6f51c6e7f84c598c1051b0dde6d29d7e"}},{"ruleId":"D1","level":"warning","message":{"text":"GameScannerConfig.CopyDiffTo (cyclomatic 17): GameScannerConfig.CopyDiffTo has cyclomatic complexity 17 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/GameScannerConfig.cs"},"region":{"startLine":249}}}],"partialFingerprints":{"codehealthFindingId/v1":"8b3e73ee78d5348890555610fc742d29699dcce7471da3170f3b9695a9f2f8c0"}},{"ruleId":"D1","level":"warning","message":{"text":"GameAction.Equals (cyclomatic 17): GameAction.Equals has cyclomatic complexity 17 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/GameAction.cs"},"region":{"startLine":324}}}],"partialFingerprints":{"codehealthFindingId/v1":"cc9a2114798546ca3bb566d1ecee11c3ffd41c53d88ad1b34e67954993deb9af"}},{"ruleId":"D1","level":"warning","message":{"text":"MainMenu.AddExtensionItems (cyclomatic 17): MainMenu.AddExtensionItems has cyclomatic complexity 17 (threshold 15). Of this number, 16 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/MainMenu.cs"},"region":{"startLine":299}}}],"partialFingerprints":{"codehealthFindingId/v1":"659f80c4a6bd73498ead55e15d4e16b2e82eacb022ad28b66a5d90741fbc5e0a"}},{"ruleId":"D1","level":"warning","message":{"text":"FullscreenTilePanel.MakeVisible (cyclomatic 17): FullscreenTilePanel.MakeVisible has cyclomatic complexity 17 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/FullscreenTilePanel.cs"},"region":{"startLine":656}}}],"partialFingerprints":{"codehealthFindingId/v1":"5480a25f0bd5072a1edef4e5c1d59697bd72c7acf75349cb8ccdf7cc83b67c4c"}},{"ruleId":"D1","level":"warning","message":{"text":"ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor (cyclomatic 17): ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor has cyclomatic complexity 17 (threshold 15). Of this number, 16 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/ExtensionsMenuViewModels.cs"},"region":{"startLine":83}}}],"partialFingerprints":{"codehealthFindingId/v1":"2f523bb6a7af2b773ec0202a6d65f5060fb9778dc4be476ba5965c63c951fa4a"}},{"ruleId":"D1","level":"warning","message":{"text":"EmulatorScanner.SearchForEmulators (cyclomatic 16): EmulatorScanner.SearchForEmulators has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":59}}}],"partialFingerprints":{"codehealthFindingId/v1":"97ffa4e05f0f890a7384c8d44b7457c58780e92c3c15a780469c89c13dc94796"}},{"ruleId":"D1","level":"warning","message":{"text":"GameScanner.LookupGameInDb (cyclomatic 16): GameScanner.LookupGameInDb has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":1020}}}],"partialFingerprints":{"codehealthFindingId/v1":"2a810b0af6477ba1df73f263d6d50f0f3f7131a50937df97ba3a567f9ccbc14b"}},{"ruleId":"D1","level":"warning","message":{"text":"PlayniteApplication.CheckOtherInstances (cyclomatic 16): PlayniteApplication.CheckOtherInstances has cyclomatic complexity 16 (threshold 15). Most of this is not in the body itself: 5 of the 16 points are its own statements and the rest belongs to 2 function literals inside it that branch (lines 934, 972). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals\u0027 work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":925}}}],"partialFingerprints":{"codehealthFindingId/v1":"b5a02b01b76f8c8639a478f247fbe872c8bab1f39f6a939ddb757f876497359d"}},{"ruleId":"D1","level":"warning","message":{"text":"StringExtensions.GetJaroWinklerSimilarity (cyclomatic 16): StringExtensions.GetJaroWinklerSimilarity has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/StringExtensions.cs"},"region":{"startLine":467}}}],"partialFingerprints":{"codehealthFindingId/v1":"4f22e9a496c4097334712d91eda5db38820377e0853d67bca948aa4cb24ddbdf"}},{"ruleId":"D1","level":"warning","message":{"text":"GameDatabase.LoadUsedItems (cyclomatic 16): GameDatabase.LoadUsedItems has cyclomatic complexity 16 (threshold 15). To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":310}}}],"partialFingerprints":{"codehealthFindingId/v1":"74c1674e146c6b2ec36afcfd37769b9d3983942cfafe749d336381c0f918e979"}},{"ruleId":"D1","level":"warning","message":{"text":"GameDatabase.GameInfoToGame (cyclomatic 16): GameDatabase.GameInfoToGame has cyclomatic complexity 16 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":1081}}}],"partialFingerprints":{"codehealthFindingId/v1":"639cbf9fad7c0d84087d81995312516a3b44182c5bf47f0c0c6e202651818fc4"}},{"ruleId":"D1","level":"warning","message":{"text":"DefaultSearchContext.GetSearchResults (cyclomatic 16): DefaultSearchContext.GetSearchResults has cyclomatic complexity 16 (threshold 15). Of this number, 15 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":128}}}],"partialFingerprints":{"codehealthFindingId/v1":"fee5afbf6a3ff1dd729619f987b76c1411c639bde1e413dc58f9636d46c6cc9a"}},{"ruleId":"D1","level":"warning","message":{"text":"FirstTimeStartupViewModel.NavigateNext (cyclomatic 16): FirstTimeStartupViewModel.NavigateNext has cyclomatic complexity 16 (threshold 15). Of this number, 12 points are the body\u0027s own statements and 4 belong to one function literal inside it that branches. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/FirstTimeStartupViewModel.cs"},"region":{"startLine":190}}}],"partialFingerprints":{"codehealthFindingId/v1":"044e06f410a507b300300761f8060b91a9f87b83199d1e351066dc21ab68749f"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.GetOrGenerateNewFieldItem (cyclomatic 16): GameEditViewModel.GetOrGenerateNewFieldItem has cyclomatic complexity 16 (threshold 15). Of this number, 14 points are the body\u0027s own statements and 2 belong to 2 function literals inside it that branch. To reduce it, separate the cases: extract each independent branch into its own named function, and where the body has guards that only reject input, fold those into early returns at the top."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":406}}}],"partialFingerprints":{"codehealthFindingId/v1":"f02a57d0eda55af064454a351f90e84f053e1306803dfb6d4ef7092ca8b8d7ac"}},{"ruleId":"D1","level":"warning","message":{"text":"GameEditViewModel.ConvertGameInfo (cyclomatic 16): GameEditViewModel.ConvertGameInfo has cyclomatic complexity 16 (threshold 15). To reduce it, split the body: these branches sit side by side rather than nested inside one another, so extracting each one on its own would leave a function per branch. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":481}}}],"partialFingerprints":{"codehealthFindingId/v1":"fbd512beeaeaf784c5770a54c9d38cc2dcbc694bfbef2bf9732aa3263a4392d3"}},{"ruleId":"D1","level":"warning","message":{"text":"DatParser.ProcessLibretroDb (cyclomatic 16): DatParser.ProcessLibretroDb has cyclomatic complexity 16 (threshold 15). Most of this is not in the body itself: 1 of the 16 points is its own statement and the rest belongs to one function literal inside it that branches (line 396). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Utilities/DatParser.cs"},"region":{"startLine":303}}}],"partialFingerprints":{"codehealthFindingId/v1":"ad66872fda8a730ead7be4c2fee020d85dcfa3478b2a04518d81bba0f83deba3"}},{"ruleId":"D2","level":"warning","message":{"text":"MetadataDownloader.DownloadMetadataAsync (cognitive 233): MetadataDownloader.DownloadMetadataAsync has cognitive complexity 233 (threshold 15). Most of this is not in the body itself: 0 of the 233 points are its own statements and the rest belongs to one function literal inside it that branches (line 318). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Metadata/MetadataDownloader.cs"},"region":{"startLine":311}}}],"partialFingerprints":{"codehealthFindingId/v1":"2c2c2416fbb6d5b93764646e5fc747572b0fa7c9440822f8acb0e42e393c6440"}},{"ruleId":"D2","level":"warning","message":{"text":"GameDatabase.MigrateNewDatabaseFormat (cognitive 190): GameDatabase.MigrateNewDatabaseFormat has cognitive complexity 190 (threshold 15). Of this number, 115 points are the body\u0027s own statements and 75 belong to 5 function literals inside it that branch. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabaseMigration.cs"},"region":{"startLine":22}}}],"partialFingerprints":{"codehealthFindingId/v1":"b87bc419025484a6562fcee9fcc1320d7d87e0e043a88191a1ca266df22b150e"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.ConfirmDialog (cognitive 145): GameEditViewModel.ConfirmDialog has cognitive complexity 145 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":525}}}],"partialFingerprints":{"codehealthFindingId/v1":"c9edf56e016e72f2fc70a15984106353ebc3da3d2fcbf40ab3ae7cb3f753615e"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.EditingGame_PropertyChanged (cognitive 130): GameEditViewModel.EditingGame_PropertyChanged has cognitive complexity 130 (threshold 15). The drivers above price the dispatch low by construction \u2014 a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full \u2014 so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelFieldChecks.cs"},"region":{"startLine":849}}}],"partialFingerprints":{"codehealthFindingId/v1":"4f404441be3de174237dd4196126b73801161a64ddc7346263d125f31031ed25"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.PlayniteApplication.ctor (cognitive 118): PlayniteApplication.PlayniteApplication.ctor has cognitive complexity 118 (threshold 15). Of this number, 116 points are the body\u0027s own statements and 2 belong to 2 function literals inside it that branch. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"db08c13a63f787ff4e92472fe2e42a51572d94b63c3933ce2fcfce9d2fd80523"}},{"ruleId":"D2","level":"warning","message":{"text":"Game.CopyDiffTo (cognitive 108): Game.CopyDiffTo has cognitive complexity 108 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1750}}}],"partialFingerprints":{"codehealthFindingId/v1":"ffedecf7b973d4420b0ba2722a7113d27dba6b4ff0d4f9a63d9b6a5e80b88ccd"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.CheckAndUpdateOffsets (cognitive 104): TGA.CheckAndUpdateOffsets has cognitive complexity 104 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":4799}}}],"partialFingerprints":{"codehealthFindingId/v1":"f74921787f7028c6ba21c11b2e42121d2d559a8c155aa0c7bcc37cd1ff4eee5b"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScanner.ScanDirectoryBase (cognitive 99): GameScanner.ScanDirectoryBase has cognitive complexity 99 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":693}}}],"partialFingerprints":{"codehealthFindingId/v1":"530f1fd46cfa5a36a001d610095de669d0c4597940b0d8865e960bf8f8877920"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScanner.Scan (cognitive 91): GameScanner.Scan has cognitive complexity 91 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":185}}}],"partialFingerprints":{"codehealthFindingId/v1":"f6f0a7aa05a5e2e8c089721f6c90bb8c5f343479d4e6d600d996152495a07acd"}},{"ruleId":"D2","level":"warning","message":{"text":"GameDatabase.ImportGames (cognitive 85): GameDatabase.ImportGames has cognitive complexity 85 (threshold 15). Of this number, 84 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":1205}}}],"partialFingerprints":{"codehealthFindingId/v1":"76f46b11866f24871699b7514ead6e7b9eea149d9bc169dfd5e4a216a5c11f29"}},{"ruleId":"D2","level":"warning","message":{"text":"Game.GetDifferences (cognitive 75): Game.GetDifferences has cognitive complexity 75 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":2032}}}],"partialFingerprints":{"codehealthFindingId/v1":"a88be0af554a4ae5a9fa3b3dbe26041b0f991f417fbb4bb34b26c6d7b8e10e87"}},{"ruleId":"D2","level":"warning","message":{"text":"GenericPlayController.Start (cognitive 74): GenericPlayController.Start has cognitive complexity 74 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":481}}}],"partialFingerprints":{"codehealthFindingId/v1":"8c7b01b675fb435e1544f3ad1b5fa7b71573747ab4af5f5308f056c0332aa236"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.GetPlayActions (cognitive 73): GamesEditor.GetPlayActions has cognitive complexity 73 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1682}}}],"partialFingerprints":{"codehealthFindingId/v1":"5f91c04786900996c7fee7db2bc366530935cbc45010640bc0aedb809e7977f0"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.LoadFunc (cognitive 70): TGA.LoadFunc has cognitive complexity 70 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5298}}}],"partialFingerprints":{"codehealthFindingId/v1":"6af7a7782829c0bd926f10b56f376644a4a882dc3b3e4ea40242bbf6fe0be362"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.GetDisplayDiffFields (cognitive 63): GameEditViewModel.GetDisplayDiffFields has cognitive complexity 63 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":56}}}],"partialFingerprints":{"codehealthFindingId/v1":"51857f793d725e61b5053493c800e34032369334090c9d3c1e34e5b2aa307f99"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.ToBitmapFunc (cognitive 61): TGA.ToBitmapFunc has cognitive complexity 61 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5681}}}],"partialFingerprints":{"codehealthFindingId/v1":"91af242aa955e31da2b2bf4ad0b2e9e63260c66e15a86387cc4cd20b994bc1c7"}},{"ruleId":"D2","level":"warning","message":{"text":"ItemsControlEx.ItemsControlEx_PreviewKeyDown (cognitive 60): ItemsControlEx.ItemsControlEx_PreviewKeyDown has cognitive complexity 60 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs"},"region":{"startLine":38}}}],"partialFingerprints":{"codehealthFindingId/v1":"e15f4161e8005f7df61245b13f8f2b6307c4d01f92b519dcbc2a00f6fc4e4458"}},{"ruleId":"D2","level":"warning","message":{"text":"EmulatorScanner.SearchForEmulators (cognitive 57): EmulatorScanner.SearchForEmulators has cognitive complexity 57 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":59}}}],"partialFingerprints":{"codehealthFindingId/v1":"9f0483c009221afe3f3c947dd604c065049d72de1549f7114250c5692e378483"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.LoadFunc (cognitive 54): TGA.LoadFunc has cognitive complexity 54 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5138}}}],"partialFingerprints":{"codehealthFindingId/v1":"72bc6e422bc5d6e4b94a50471a34b589f976854778d6704f68a8ea66e3696486"}},{"ruleId":"D2","level":"warning","message":{"text":"Main.OnApplyTemplate (cognitive 49): Main.OnApplyTemplate has cognitive complexity 49 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/Views/Main.cs"},"region":{"startLine":226}}}],"partialFingerprints":{"codehealthFindingId/v1":"4655ea84965fd1b65df011e17c129490ca83172678117631980578f59bd9e9f0"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.Controllers_Stopped (cognitive 48): GamesEditor.Controllers_Stopped has cognitive complexity 48 (threshold 15). Of this number, 28 points are the body\u0027s own statements and 20 belong to 2 function literals inside it that branch. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1416}}}],"partialFingerprints":{"codehealthFindingId/v1":"2da444412c6869c35027cbe32fc206fa114fbaf3cab43cf34921b221067ff2bb"}},{"ruleId":"D2","level":"warning","message":{"text":"Backup.RestoreBackup (cognitive 47): Backup.RestoreBackup has cognitive complexity 47 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Backup.cs"},"region":{"startLine":212}}}],"partialFingerprints":{"codehealthFindingId/v1":"933366a5ddef0482ef874b17fbb7576204a1425c0f1f9d3090a74c461c95e4dd"}},{"ruleId":"D2","level":"warning","message":{"text":"MenuItems.GetSearchGameMenuItems (cognitive 47): MenuItems.GetSearchGameMenuItems has cognitive complexity 47 (threshold 15). Of this number, 44 points are the body\u0027s own statements and 3 belong to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuItems.cs"},"region":{"startLine":164}}}],"partialFingerprints":{"codehealthFindingId/v1":"3f9a5dbc52f962f2fcd89e68c8166470d08342f4029d2a21b09287c5abc81cd9"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScanner.LookupGameInDb (cognitive 46): GameScanner.LookupGameInDb has cognitive complexity 46 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":1020}}}],"partialFingerprints":{"codehealthFindingId/v1":"2b1905107d2a225a8c49356107740784c2731b577144e351bc107edbf740ab6e"}},{"ruleId":"D2","level":"warning","message":{"text":"CloneObject.CopyProperties (cognitive 46): CloneObject.CopyProperties has cognitive complexity 46 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/CloneObject.cs"},"region":{"startLine":113}}}],"partialFingerprints":{"codehealthFindingId/v1":"baafb3b39021208e8a7f8016afe99e03a27e8488f512078692c1f2e22fc0624b"}},{"ruleId":"D2","level":"warning","message":{"text":"DesktopAppViewModel.OnFileDropped (cognitive 45): DesktopAppViewModel.OnFileDropped has cognitive complexity 45 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":836}}}],"partialFingerprints":{"codehealthFindingId/v1":"1fceb295a727a3d4939c7afc33f35c18be7da42d3b29e869b3844ae080808ab1"}},{"ruleId":"D2","level":"warning","message":{"text":"Backup.BackupData (cognitive 44): Backup.BackupData has cognitive complexity 44 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Backup.cs"},"region":{"startLine":73}}}],"partialFingerprints":{"codehealthFindingId/v1":"c761c6846a627fb468cf70a3bd0554adb56ef2e6a5117abec71d6bbf556da688"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.PlayGame (cognitive 44): GamesEditor.PlayGame has cognitive complexity 44 (threshold 15). Of this number, 43 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":189}}}],"partialFingerprints":{"codehealthFindingId/v1":"e2739b1ca35b7625b0b3546bd0749113a027effd5d09b054d112ffcccc23c77e"}},{"ruleId":"D2","level":"warning","message":{"text":"MetadataDownloader.ProcessField (cognitive 44): MetadataDownloader.ProcessField has cognitive complexity 44 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Metadata/MetadataDownloader.cs"},"region":{"startLine":136}}}],"partialFingerprints":{"codehealthFindingId/v1":"cd73fb14d25eb5bef9fddeb0429b0ff70ef97e4d4bec5d0b2787257ceaa29e8f"}},{"ruleId":"D2","level":"warning","message":{"text":"GenericPlayController.StartEmulator (cognitive 44): GenericPlayController.StartEmulator has cognitive complexity 44 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"559583405b3eb874c42ae9e74452283a4cf3ca52ef870b2191b78167088e033e"}},{"ruleId":"D2","level":"warning","message":{"text":"MainMenu.AddExtensionItems (cognitive 44): MainMenu.AddExtensionItems has cognitive complexity 44 (threshold 15). Of this number, 39 points are the body\u0027s own statements and 5 belong to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/MainMenu.cs"},"region":{"startLine":299}}}],"partialFingerprints":{"codehealthFindingId/v1":"038f4e7a0afee19c534a58824f768d3c2a2248b2c13543755817d3622e5923ff"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor (cognitive 44): ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor has cognitive complexity 44 (threshold 15). Of this number, 40 points are the body\u0027s own statements and 4 belong to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/ExtensionsMenuViewModels.cs"},"region":{"startLine":222}}}],"partialFingerprints":{"codehealthFindingId/v1":"037c954a4a2bb676ec2538cdbaa4e2127526a8e151b9743300c25f558c7414a8"}},{"ruleId":"D2","level":"warning","message":{"text":"DatabaseExplorer.LoadValues (cognitive 43): DatabaseExplorer.LoadValues has cognitive complexity 43 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":723}}}],"partialFingerprints":{"codehealthFindingId/v1":"4d76bc7ec64a5fe41db9eea5c2a4502858fb4d10471512850980cf9f745624bb"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.GetOrGenerateNewFieldItem (cognitive 43): GameEditViewModel.GetOrGenerateNewFieldItem has cognitive complexity 43 (threshold 15). Of this number, 41 points are the body\u0027s own statements and 2 belong to 2 function literals inside it that branch. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":406}}}],"partialFingerprints":{"codehealthFindingId/v1":"66759f88b14dedf6562cfc6dacc5c8136570680af17560fe3b8daef1661d7a79"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.CalculateGameSize (cognitive 42): GamesEditor.CalculateGameSize has cognitive complexity 42 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":566}}}],"partialFingerprints":{"codehealthFindingId/v1":"fe88913a464920a66006c3bfeee14db9e00a8dd2a199d925018d48f23b5a2c58"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.SaveFunc (cognitive 40): TGA.SaveFunc has cognitive complexity 40 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5517}}}],"partialFingerprints":{"codehealthFindingId/v1":"84dd5a365d4a70f1f65a2afd3ab92a2120fa5468351b1f49f9a7661ebccd054f"}},{"ruleId":"D2","level":"warning","message":{"text":"ImageSourceManager.GetImage (cognitive 40): ImageSourceManager.GetImage has cognitive complexity 40 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ImageSourceManager.cs"},"region":{"startLine":160}}}],"partialFingerprints":{"codehealthFindingId/v1":"8f8d71bec196a90b263cd3508fa610b6ad8619cc7420f9c41debd5e9c03ddac1"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.Application_Startup (cognitive 39): PlayniteApplication.Application_Startup has cognitive complexity 39 (threshold 15). Of this number, 37 points are the body\u0027s own statements and 2 belong to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":599}}}],"partialFingerprints":{"codehealthFindingId/v1":"21d690cdb70f758a12b52f24ce667d5235dada49574368a1fff8be4768770f38"}},{"ruleId":"D2","level":"warning","message":{"text":"Themes.UpdateTheme (cognitive 39): Themes.UpdateTheme has cognitive complexity 39 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Toolbox/Themes.cs"},"region":{"startLine":272}}}],"partialFingerprints":{"codehealthFindingId/v1":"60ca6a7e5c9a20da57f0f05c78ce51286c961e824c16a8b41cbeb103c43c0db6"}},{"ruleId":"D2","level":"warning","message":{"text":"GameMenu.AddExtensionItems (cognitive 38): GameMenu.AddExtensionItems has cognitive complexity 38 (threshold 15). Of this number, 33 points are the body\u0027s own statements and 5 belong to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs"},"region":{"startLine":580}}}],"partialFingerprints":{"codehealthFindingId/v1":"b2a1ae0198a9d507ed9c80878e84a3b1da42250607b19bfa7cbf02eb7e31b446"}},{"ruleId":"D2","level":"warning","message":{"text":"BitmapExtensions.BitmapFromStream (cognitive 37): BitmapExtensions.BitmapFromStream has cognitive complexity 37 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/BitmapExtensions.cs"},"region":{"startLine":249}}}],"partialFingerprints":{"codehealthFindingId/v1":"209d05ed73437a96ebdd855f4da02f37d0296d150fc99d82de8214a005ca5856"}},{"ruleId":"D2","level":"warning","message":{"text":"DatabaseFilter.UpdateAllCollections (cognitive 37): DatabaseFilter.UpdateAllCollections has cognitive complexity 37 (threshold 15). The drivers above price the dispatch low by construction \u2014 a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full \u2014 so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseFilter.cs"},"region":{"startLine":375}}}],"partialFingerprints":{"codehealthFindingId/v1":"d2d64836a8bbc72eebe36df4789303b3c0a0c6ed1aeb1bf9d539d5996dcecc89"}},{"ruleId":"D2","level":"warning","message":{"text":"FadeImage.LoadNewSource (cognitive 36): FadeImage.LoadNewSource has cognitive complexity 36 (threshold 15). Of this number, 32 points are the body\u0027s own statements and 4 belong to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controls/FadeImage.xaml.cs"},"region":{"startLine":259}}}],"partialFingerprints":{"codehealthFindingId/v1":"97308dad36fff0818e7ec971ebf742d995996ef196f04ce819501766df9c471b"}},{"ruleId":"D2","level":"warning","message":{"text":"SdkHelpers.ResolveUiItemIcon (cognitive 36): SdkHelpers.ResolveUiItemIcon has cognitive complexity 36 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SdkHelpers.cs"},"region":{"startLine":23}}}],"partialFingerprints":{"codehealthFindingId/v1":"3ef8b157f3b2da827cb84427abdab186cda058db06a19bf9719d755189204f73"}},{"ruleId":"D2","level":"warning","message":{"text":"EmulatedGamesImportViewModel.StartScan (cognitive 36): EmulatedGamesImportViewModel.StartScan has cognitive complexity 36 (threshold 15). Of this number, 28 points are the body\u0027s own statements and 8 belong to 4 function literals inside it that branch. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatedGamesImportViewModel.cs"},"region":{"startLine":331}}}],"partialFingerprints":{"codehealthFindingId/v1":"90cbc24fe7f807f378df8cc18cea43457b0bf2f4b4f614d32148ece161203da8"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor (cognitive 36): ExtensionsMenuViewModels.ExtensionsMenuViewModels.ctor has cognitive complexity 36 (threshold 15). Of this number, 32 points are the body\u0027s own statements and 4 belong to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/ExtensionsMenuViewModels.cs"},"region":{"startLine":83}}}],"partialFingerprints":{"codehealthFindingId/v1":"b69d67653caa74e37a082dc6b92e9ea35339e496bbd29941ccfd4b06349f405f"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteSettings.LoadSettings (cognitive 35): PlayniteSettings.LoadSettings has cognitive complexity 35 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":2352}}}],"partialFingerprints":{"codehealthFindingId/v1":"2a2bcd81a9178ea21dab4f7c3fa299059d05cfb63c1778a53e810f88250d1105"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenAppViewModel.Fullscreen_PropertyChanged (cognitive 35): FullscreenAppViewModel.Fullscreen_PropertyChanged has cognitive complexity 35 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":579}}}],"partialFingerprints":{"codehealthFindingId/v1":"6498fd8c29f531deef51d39a1e36c6aad254f35beb9b02fdabe30017b99b0b29"}},{"ruleId":"D2","level":"warning","message":{"text":"CategoryConfigViewModel.SetCategoryStates (cognitive 34): CategoryConfigViewModel.SetCategoryStates has cognitive complexity 34 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/CategoryConfigViewModel.cs"},"region":{"startLine":205}}}],"partialFingerprints":{"codehealthFindingId/v1":"70cdf77792e440c854343d7d85dce6b653d44d012ba0f437c26d20a517c9b6db"}},{"ruleId":"D2","level":"warning","message":{"text":"StatisticsViewModel.FillData (cognitive 33): StatisticsViewModel.FillData has cognitive complexity 33 (threshold 15). Of this number, 30 points are the body\u0027s own statements and 3 belong to 2 function literals inside it that branch. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/StatisticsViewModel.cs"},"region":{"startLine":325}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac2200022c7e8ffb5e1af78121307aa3f77cdf61d54a6863331e735b108727c7"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenAppViewModel.InitializeCommands (cognitive 33): FullscreenAppViewModel.InitializeCommands has cognitive complexity 33 (threshold 15). Most of this is not in the body itself: 0 of the 33 points are its own statements and the rest belongs to 12 function literals inside it that branch (lines 56, 205, 266, \u2026). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals\u0027 work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs"},"region":{"startLine":45}}}],"partialFingerprints":{"codehealthFindingId/v1":"04875ca570873e53e12d79f96ebf0370637615b09c652aba53bf03fce37d231f"}},{"ruleId":"D2","level":"warning","message":{"text":"Programs.GetUWPApps (cognitive 32): Programs.GetUWPApps has cognitive complexity 32 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Programs2.cs"},"region":{"startLine":294}}}],"partialFingerprints":{"codehealthFindingId/v1":"e0ccc4169b07140b399453cd3620d5139bf6b3b2c2c4d15b72cc0e1232cdcb69"}},{"ruleId":"D2","level":"warning","message":{"text":"ThemeManager.GetAvailableThemes (cognitive 32): ThemeManager.GetAvailableThemes has cognitive complexity 32 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Themes.cs"},"region":{"startLine":235}}}],"partialFingerprints":{"codehealthFindingId/v1":"c20b317058f80c04f8104c5039fde55660266e4b1698ee6a181fba586665eec5"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScannerConfig.CopyDiffTo (cognitive 32): GameScannerConfig.CopyDiffTo has cognitive complexity 32 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/GameScannerConfig.cs"},"region":{"startLine":249}}}],"partialFingerprints":{"codehealthFindingId/v1":"cc3a51a3c5250eed51a098eae65b924a50480d8f734d0bf62d5726ed946e2dfb"}},{"ruleId":"D2","level":"warning","message":{"text":"FileReaderV7.GetDocuments (cognitive 31): FileReaderV7.GetDocuments has cognitive complexity 31 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs"},"region":{"startLine":653}}}],"partialFingerprints":{"codehealthFindingId/v1":"e51d9ddf69a6cb93b2dfca28d638e794fe098500b2c7c520c9e3a6d8507223cc"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.PipeService_CommandExecuted (cognitive 31): PlayniteApplication.PipeService_CommandExecuted has cognitive complexity 31 (threshold 15). The drivers above price the dispatch low by construction \u2014 a dispatch is charged once however many cases it lists, while each branch inside an arm is charged in full \u2014 so most of this count is what the case bodies hold, and the arms are where it can be reduced. To reduce it, keep the dispatch but shrink the arms: move each non-trivial case body into its own named function (or onto the value being matched) so the dispatch reads one line per case, and group related cases into a sub-dispatch. Keep every case explicit, and make the behaviour for cases you do not list a deliberate choice rather than an accident."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":780}}}],"partialFingerprints":{"codehealthFindingId/v1":"77fe3880350bf9aae7d38da229f40a6d9defd2e7f90ecbe23e26bcfcad447da4"}},{"ruleId":"D2","level":"warning","message":{"text":"GameDatabase.AddFile (cognitive 31): GameDatabase.AddFile has cognitive complexity 31 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":833}}}],"partialFingerprints":{"codehealthFindingId/v1":"1b127fc281595d89f5194e34d7a49a671cf379f6cda303631dfe3e31906bb47e"}},{"ruleId":"D2","level":"warning","message":{"text":"ThemeFile.GetFilePath (cognitive 31): ThemeFile.GetFilePath has cognitive complexity 31 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/Markup/ThemeFile.cs"},"region":{"startLine":107}}}],"partialFingerprints":{"codehealthFindingId/v1":"9110c1687001cbb1fe9051b7df587cf4eea0301b919dbd2dee74cbc37dc6a821"}},{"ruleId":"D2","level":"warning","message":{"text":"FilterSettings.ClearFilters (cognitive 31): FilterSettings.ClearFilters has cognitive complexity 31 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":956}}}],"partialFingerprints":{"codehealthFindingId/v1":"42123c417b6edf2d0cd601e1d0d253d5760ae2dc4fd264733ba3564b2ce7acba"}},{"ruleId":"D2","level":"warning","message":{"text":"FirstTimeStartupViewModel.NavigateNext (cognitive 31): FirstTimeStartupViewModel.NavigateNext has cognitive complexity 31 (threshold 15). Of this number, 21 points are the body\u0027s own statements and 10 belong to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/FirstTimeStartupViewModel.cs"},"region":{"startLine":190}}}],"partialFingerprints":{"codehealthFindingId/v1":"67b5f7722c92fe866b30e2a82836a33c7b7f325f0885cb625f5d5b52266ec261"}},{"ruleId":"D2","level":"warning","message":{"text":"ControlTemplateTools.InitializePluginControls (cognitive 30): ControlTemplateTools.InitializePluginControls has cognitive complexity 30 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ControlTemplateTools.cs"},"region":{"startLine":19}}}],"partialFingerprints":{"codehealthFindingId/v1":"a09d070cf206cba11137274d914b08f786a4b2b66e1918060991a4d19419595b"}},{"ruleId":"D2","level":"warning","message":{"text":"ScannedGame.ToGame (cognitive 30): ScannedGame.ToGame has cognitive complexity 30 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":1333}}}],"partialFingerprints":{"codehealthFindingId/v1":"44a8f9691919ae1a833cabbd9b8580ebaf32884ee29dfb757ce787d3fe696f86"}},{"ruleId":"D2","level":"warning","message":{"text":"GameExtensions.GetGameFromExecutable (cognitive 30): GameExtensions.GetGameFromExecutable has cognitive complexity 30 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/GameExtensions.cs"},"region":{"startLine":58}}}],"partialFingerprints":{"codehealthFindingId/v1":"c13914acbd33658999d4df4b08751d5c1f420a5a4303b4be73c756451c28e102"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesCollectionViewEntry.GetAdvancedGroupedEntry (cognitive 30): GamesCollectionViewEntry.GetAdvancedGroupedEntry has cognitive complexity 30 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesCollectionViewEntry.cs"},"region":{"startLine":273}}}],"partialFingerprints":{"codehealthFindingId/v1":"58e038584a0df29df60067604ec3e1f6a7de216878ffd8769e47e2fe571c5c52"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionFactory.LoadPlugins (cognitive 30): ExtensionFactory.LoadPlugins has cognitive complexity 30 (threshold 15). Of this number, 29 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":390}}}],"partialFingerprints":{"codehealthFindingId/v1":"e45203f523de7f58395af16cf021840cc3ec4f5b2b0e7b795df2d5ab3c1ee5f2"}},{"ruleId":"D2","level":"warning","message":{"text":"FilterSettings.ApplyFilter (cognitive 30): FilterSettings.ApplyFilter has cognitive complexity 30 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":1221}}}],"partialFingerprints":{"codehealthFindingId/v1":"588abf7b964dd02599adb5756c92ef66bcb66721a1052b467f2b8747ea2c06e3"}},{"ruleId":"D2","level":"warning","message":{"text":"ThemeManager.ApplyTheme (cognitive 30): ThemeManager.ApplyTheme has cognitive complexity 30 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Themes.cs"},"region":{"startLine":92}}}],"partialFingerprints":{"codehealthFindingId/v1":"e3b9058f1a0cb73a05712c2108f645bb23350a9e1a1b76ebd55d3ccb1723f7c0"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesGridView.GetColumn (cognitive 30): GamesGridView.GetColumn has cognitive complexity 30 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/GamesGridView.xaml.cs"},"region":{"startLine":208}}}],"partialFingerprints":{"codehealthFindingId/v1":"70d7290391febbd7576cfc39a136eea73828b344cbb0420ca62538ce2ddf5f86"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionFactory.GetInstalledManifests (cognitive 29): ExtensionFactory.GetInstalledManifests has cognitive complexity 29 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":231}}}],"partialFingerprints":{"codehealthFindingId/v1":"000c0f139103a6d414906e7131aadbdb186721e7cf3e8ac8c02dc14f1fd2ac10"}},{"ruleId":"D2","level":"warning","message":{"text":"GameTools.GetMultiGameEditObject (cognitive 29): GameTools.GetMultiGameEditObject has cognitive complexity 29 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GameTools.cs"},"region":{"startLine":28}}}],"partialFingerprints":{"codehealthFindingId/v1":"a1da5569cf4f862e8145ad425acfb30ee4fea29e2ef16a99c2397d9649e0cf97"}},{"ruleId":"D2","level":"warning","message":{"text":"DesktopCollectionView.Database_GamesCollectionChanged (cognitive 29): DesktopCollectionView.Database_GamesCollectionChanged has cognitive complexity 29 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopCollectionView.cs"},"region":{"startLine":568}}}],"partialFingerprints":{"codehealthFindingId/v1":"438cd30f0479aa9a69878f6636eea80b60197d11cb8388527f91ecdd1150e2c8"}},{"ruleId":"D2","level":"warning","message":{"text":"CategoryConfigViewModel.SetCategories (cognitive 29): CategoryConfigViewModel.SetCategories has cognitive complexity 29 (threshold 15). Of this number, 26 points are the body\u0027s own statements and 3 belong to 2 function literals inside it that branch. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/CategoryConfigViewModel.cs"},"region":{"startLine":142}}}],"partialFingerprints":{"codehealthFindingId/v1":"0e2b845bbcfd583b0759384fce22be90109560328ce0a8cff12be317a8648635"}},{"ruleId":"D2","level":"warning","message":{"text":"DatParser.ParseProperty (cognitive 29): DatParser.ParseProperty has cognitive complexity 29 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Utilities/DatParser.cs"},"region":{"startLine":129}}}],"partialFingerprints":{"codehealthFindingId/v1":"8b83aa49d1482b88c89c47747daf5632e029fc15fde16c97f4f012571230c691"}},{"ruleId":"D2","level":"warning","message":{"text":"FilterMatcher.Match (cognitive 28): FilterMatcher.Match has cognitive complexity 28 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase_Filters.cs"},"region":{"startLine":60}}}],"partialFingerprints":{"codehealthFindingId/v1":"23cc5ca5618452853017958195dbbcee3b40cd7ae1fb6c396a6ac526e5ba6a95"}},{"ruleId":"D2","level":"warning","message":{"text":"MenuItems.GetSearchExtensionsMainMenuItem (cognitive 28): MenuItems.GetSearchExtensionsMainMenuItem has cognitive complexity 28 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuItems.cs"},"region":{"startLine":83}}}],"partialFingerprints":{"codehealthFindingId/v1":"aa882b2e10cea74c075b8d3119fc521fd55f8075db85f2dd1cdc2c57c57a5fe7"}},{"ruleId":"D2","level":"warning","message":{"text":"GenericPlayController.StartTracking (cognitive 28): GenericPlayController.StartTracking has cognitive complexity 28 (threshold 15). Most of this is not in the body itself: 1 of the 28 points is its own statement and the rest belongs to one function literal inside it that branches (line 684). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":670}}}],"partialFingerprints":{"codehealthFindingId/v1":"d063ee332e7213b67ecd6e109bdf2464bb842202d9bbb45ecdbd1a2522cafc5f"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.LoadNewMetadata (cognitive 28): GameEditViewModel.LoadNewMetadata has cognitive complexity 28 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":252}}}],"partialFingerprints":{"codehealthFindingId/v1":"3fa9cbc18676aaf12a1fd13d878a675b20e0423681e46f19f18db7ac8b0e35c2"}},{"ruleId":"D2","level":"warning","message":{"text":"MetadataComparisonViewModel.ConfirmDialog (cognitive 28): MetadataComparisonViewModel.ConfirmDialog has cognitive complexity 28 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs"},"region":{"startLine":264}}}],"partialFingerprints":{"codehealthFindingId/v1":"151f47518f1ec93b06ed472ef4a4deb6322635ad0bb9ba1a451bf1e5cf82736e"}},{"ruleId":"D2","level":"warning","message":{"text":"GameDatabase.LoadUsedItems (cognitive 27): GameDatabase.LoadUsedItems has cognitive complexity 27 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":310}}}],"partialFingerprints":{"codehealthFindingId/v1":"a9e161452bb82d499e0b80011b3794b8ef51d3eed2022893c6b5558b5975d268"}},{"ruleId":"D2","level":"warning","message":{"text":"GameMenu.InitializeItems (cognitive 27): GameMenu.InitializeItems has cognitive complexity 27 (threshold 15). Of this number, 23 points are the body\u0027s own statements and 4 belong to one function literal inside it that branches. To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs"},"region":{"startLine":105}}}],"partialFingerprints":{"codehealthFindingId/v1":"75b665128b663d4a829ae296746159bab0e13f6a7f9466605ce7b6e501c80122"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.Init (cognitive 27): GameEditViewModel.Init has cognitive complexity 27 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":319}}}],"partialFingerprints":{"codehealthFindingId/v1":"68e57775ec098b11c670d51072e506f0795d3b22570ec6d117424e4311ee32be"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.CheckOtherInstances (cognitive 26): PlayniteApplication.CheckOtherInstances has cognitive complexity 26 (threshold 15). Most of this is not in the body itself: 7 of the 26 points are its own statements and the rest belongs to 2 function literals inside it that branch (lines 934, 972). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals\u0027 work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":925}}}],"partialFingerprints":{"codehealthFindingId/v1":"b083708d0d9e59f5a39cf2d2e678caa8ce51565ae14eb180346a9556a197588b"}},{"ruleId":"D2","level":"warning","message":{"text":"GenericPlayController.StartEmulatorProcess (cognitive 26): GenericPlayController.StartEmulatorProcess has cognitive complexity 26 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":221}}}],"partialFingerprints":{"codehealthFindingId/v1":"adb8f225f78ccbcfdfdd541056a6c6330d6bedf738a85d7547731218a9b014cb"}},{"ruleId":"D2","level":"warning","message":{"text":"GridViewPanel.MeasureOverride (cognitive 26): GridViewPanel.MeasureOverride has cognitive complexity 26 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/GridViewPanel.cs"},"region":{"startLine":111}}}],"partialFingerprints":{"codehealthFindingId/v1":"a0dfbb6f42d657722d621311fe5ca55915afc5d90939df5be1acadbdbb28bdc0"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.RLE_Encode (cognitive 25): TGA.RLE_Encode has cognitive complexity 25 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":5609}}}],"partialFingerprints":{"codehealthFindingId/v1":"f69f71ad027b88cb12bb2764fc0fc28769e2edabfdd46c953a0eaf94cca999ef"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionInstaller.InstallExtensionQueue (cognitive 25): ExtensionInstaller.InstallExtensionQueue has cognitive complexity 25 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionInstaller.cs"},"region":{"startLine":118}}}],"partialFingerprints":{"codehealthFindingId/v1":"cb68c6b19a4668970f2b365f2373f9d545ca879daab39a18b1f7151d72541612"}},{"ruleId":"D2","level":"warning","message":{"text":"GameTaskView.ComboEmulatorConfig_SelectionChanged (cognitive 25): GameTaskView.ComboEmulatorConfig_SelectionChanged has cognitive complexity 25 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/GameTaskView.xaml.cs"},"region":{"startLine":388}}}],"partialFingerprints":{"codehealthFindingId/v1":"d965e7d4163576e869771edcfd7af984dd857cb81f16a469511dc90a0298f32b"}},{"ruleId":"D2","level":"warning","message":{"text":"SettingsViewModel.ConfirmDialog (cognitive 25): SettingsViewModel.ConfirmDialog has cognitive complexity 25 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/SettingsViewModel.cs"},"region":{"startLine":525}}}],"partialFingerprints":{"codehealthFindingId/v1":"6ed02a4d82b0fdcbebe9e2e1c1e0e9e09b49dbe9043498e227cd1ac85be904ea"}},{"ruleId":"D2","level":"warning","message":{"text":"SortableNameConverter.ConvertRomanNumeralToInt (cognitive 24): SortableNameConverter.ConvertRomanNumeralToInt has cognitive complexity 24 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SortableNameConverter.cs"},"region":{"startLine":139}}}],"partialFingerprints":{"codehealthFindingId/v1":"d88f0ed491f543f6c82d4118a483054f5ec1bd8740edc5254a2c6569a6aa8290"}},{"ruleId":"D2","level":"warning","message":{"text":"FileReaderV7.ReadPage (cognitive 24): FileReaderV7.ReadPage has cognitive complexity 24 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs"},"region":{"startLine":714}}}],"partialFingerprints":{"codehealthFindingId/v1":"72aff9bf41e388feb2802a78fb97b23e18441b1d0bdcc0caa5cdb69b439c5a00"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScanner.ScanDirectory (cognitive 24): GameScanner.ScanDirectory has cognitive complexity 24 (threshold 15). Of this number, 22 points are the body\u0027s own statements and 2 belong to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":521}}}],"partialFingerprints":{"codehealthFindingId/v1":"dd1f39e6993de0d1d1fc8a0819e7a002991faf648e5805bcba4eb99234e42d34"}},{"ruleId":"D2","level":"warning","message":{"text":"StringExtensions.GetJaroWinklerSimilarity (cognitive 24): StringExtensions.GetJaroWinklerSimilarity has cognitive complexity 24 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/StringExtensions.cs"},"region":{"startLine":467}}}],"partialFingerprints":{"codehealthFindingId/v1":"2e0851c89db207fc2eae037d11532cfe2c3227b0b8b2dc7848bc0e2892462628"}},{"ruleId":"D2","level":"warning","message":{"text":"MainViewModelBase.AddFilterPreset (cognitive 24): MainViewModelBase.AddFilterPreset has cognitive complexity 24 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/MainViewModelBase.cs"},"region":{"startLine":412}}}],"partialFingerprints":{"codehealthFindingId/v1":"095541cebbd0a894be6ec27268c2b75729ca4511e1706c6009e8ccb7548de603"}},{"ruleId":"D2","level":"warning","message":{"text":"SearchViewModel.TextBoxKeyDown (cognitive 24): SearchViewModel.TextBoxKeyDown has cognitive complexity 24 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":814}}}],"partialFingerprints":{"codehealthFindingId/v1":"1bf209def3ed2d145f88542f7c465e3dc18214ab491c60e55a68dcc8bdf801ec"}},{"ruleId":"D2","level":"warning","message":{"text":"SearchViewModel.PerformSearch (cognitive 23): SearchViewModel.PerformSearch has cognitive complexity 23 (threshold 15). Most of this is not in the body itself: 11 of the 23 points are its own statements and the rest belongs to one function literal inside it that branches (line 736). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":717}}}],"partialFingerprints":{"codehealthFindingId/v1":"0593a3f7f60c600f3ffd73bf59f55af1f3a41f6126933433b5ef52be8fd12cdb"}},{"ruleId":"D2","level":"warning","message":{"text":"BsonReader.ReadElement (cognitive 22): BsonReader.ReadElement has cognitive complexity 22 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs"},"region":{"startLine":80}}}],"partialFingerprints":{"codehealthFindingId/v1":"a83321b2806b05e0b785c9d9b3504dd2610a359b366b947d163e26f5fb0b6bce"}},{"ruleId":"D2","level":"warning","message":{"text":"SortableNameConverter.Convert (cognitive 21): SortableNameConverter.Convert has cognitive complexity 21 (threshold 15). Most of this is not in the body itself: 1 of the 21 points is its own statement and the rest belongs to one function literal inside it that branches (line 75). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SortableNameConverter.cs"},"region":{"startLine":66}}}],"partialFingerprints":{"codehealthFindingId/v1":"554f055d48d0b85f89b8f57263885a92dfea03ddcfbb5eb256ca6947fd61ce36"}},{"ruleId":"D2","level":"warning","message":{"text":"GenericTypeConverter.Convert (cognitive 21): GenericTypeConverter.Convert has cognitive complexity 21 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Converters/GenericTypeConverter.cs"},"region":{"startLine":22}}}],"partialFingerprints":{"codehealthFindingId/v1":"417dc63d2a527eb779bb083eddf2898b0ff646e5e98f27f0038d96f786d10071"}},{"ruleId":"D2","level":"warning","message":{"text":"WindowBase.OnApplyTemplate (cognitive 21): WindowBase.OnApplyTemplate has cognitive complexity 21 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controls/WindowBase.cs"},"region":{"startLine":299}}}],"partialFingerprints":{"codehealthFindingId/v1":"32e75f37392fca0d28284be7f99cae33d6df4ab7885195db0e00007651a30b00"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionFactory.LoadPlugins (cognitive 21): ExtensionFactory.LoadPlugins has cognitive complexity 21 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":461}}}],"partialFingerprints":{"codehealthFindingId/v1":"3c64ac53137b1cfcb3d69b5b51f89736ca8f25b44e9030fcb6206e98ab7af6ac"}},{"ruleId":"D2","level":"warning","message":{"text":"ThemeManager.ApplyFullscreenButtonPrompts (cognitive 21): ThemeManager.ApplyFullscreenButtonPrompts has cognitive complexity 21 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Themes.cs"},"region":{"startLine":53}}}],"partialFingerprints":{"codehealthFindingId/v1":"a2400fb5cb6a9917ed11618acc4a40bceeff5b04d7221aa363d5d2521c3722d7"}},{"ruleId":"D2","level":"warning","message":{"text":"EmulatorsViewModel.CheckUnsavedChanges (cognitive 21): EmulatorsViewModel.CheckUnsavedChanges has cognitive complexity 21 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs"},"region":{"startLine":368}}}],"partialFingerprints":{"codehealthFindingId/v1":"c46f4eb82ba192d37c1ef355c25458cda0f7bd619cb6a2bcd76acc119fe3a8ce"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.CurrentDomain_UnhandledException (cognitive 20): PlayniteApplication.CurrentDomain_UnhandledException has cognitive complexity 20 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":496}}}],"partialFingerprints":{"codehealthFindingId/v1":"cdb24096abe5041671b9e811fcf234cc08bb0a48b6d6e57d8329755e0ff274d1"}},{"ruleId":"D2","level":"warning","message":{"text":"DefaultSearchContext.GetSearchResults (cognitive 20): DefaultSearchContext.GetSearchResults has cognitive complexity 20 (threshold 15). Of this number, 19 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":128}}}],"partialFingerprints":{"codehealthFindingId/v1":"36373650b12189076a8394e1f0c307e24c11e396bb30c3120d043f8ecf06f4dc"}},{"ruleId":"D2","level":"warning","message":{"text":"DatabaseFieldsManagerViewModel.UpdatePlatformsCollection (cognitive 20): DatabaseFieldsManagerViewModel.UpdatePlatformsCollection has cognitive complexity 20 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DatabaseFieldsManagerViewModel.cs"},"region":{"startLine":740}}}],"partialFingerprints":{"codehealthFindingId/v1":"d79b3bb9201149a318fac672dca5efa1664ed264fbf05cbe6444589cb5341c30"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.CheckForUpdates (cognitive 19): PlayniteApplication.CheckForUpdates has cognitive complexity 19 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":1342}}}],"partialFingerprints":{"codehealthFindingId/v1":"e011b0e5f614fd58c9390a22c11e10b8864f7ed01732c3b2938f28b29965e88c"}},{"ruleId":"D2","level":"warning","message":{"text":"FocusBahaviors.FocusBindingPropertyChanged (cognitive 19): FocusBahaviors.FocusBindingPropertyChanged has cognitive complexity 19 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Behaviors/FocusBahaviors.cs"},"region":{"startLine":36}}}],"partialFingerprints":{"codehealthFindingId/v1":"700397ed3e7f3347e4934b1d0f53867403ead88aa4140ec0c3d14e9b3952df7b"}},{"ruleId":"D2","level":"warning","message":{"text":"TGA.GetInfo (cognitive 19): TGA.GetInfo has cognitive complexity 19 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":4703}}}],"partialFingerprints":{"codehealthFindingId/v1":"096e67baed8149e011a1c421ba4e503bbf74213ac88906d57f1e611a1968377f"}},{"ruleId":"D2","level":"warning","message":{"text":"Xml.AreEqual (cognitive 19): Xml.AreEqual has cognitive complexity 19 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Xml.cs"},"region":{"startLine":14}}}],"partialFingerprints":{"codehealthFindingId/v1":"fd2be12b56cfada8200def32dd32079fa466814885a0a370b293fc703ec60eb7"}},{"ruleId":"D2","level":"warning","message":{"text":"GameDatabase.OpenDatabase (cognitive 19): GameDatabase.OpenDatabase has cognitive complexity 19 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":502}}}],"partialFingerprints":{"codehealthFindingId/v1":"154a211f5ac2bbe9080749ff2931fb686b3c5e7b55f826376b07147a4c2eec2a"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.RemoveGames (cognitive 19): GamesEditor.RemoveGames has cognitive complexity 19 (threshold 15). Of this number, 18 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":938}}}],"partialFingerprints":{"codehealthFindingId/v1":"6f76d8c5bfd656c78dab41e88e754dba70b256b40f91207ebd881f5fe0eaef29"}},{"ruleId":"D2","level":"warning","message":{"text":"Game.GetScoreGroup (cognitive 19): Game.GetScoreGroup has cognitive complexity 19 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1597}}}],"partialFingerprints":{"codehealthFindingId/v1":"53de307c004304cdbf6521518c6373f94015aa967fe8eecb5c1be057e5546c51"}},{"ruleId":"D2","level":"warning","message":{"text":"GameScanner.ParseExclusions (cognitive 18): GameScanner.ParseExclusions has cognitive complexity 18 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":401}}}],"partialFingerprints":{"codehealthFindingId/v1":"cc04cdd64b4c1ff2caafab415b838ddeb9302f448d76da494e6ecb5ddd9ec5dd"}},{"ruleId":"D2","level":"warning","message":{"text":"PlayniteApplication.ProcessUriRequest (cognitive 18): PlayniteApplication.ProcessUriRequest has cognitive complexity 18 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":1118}}}],"partialFingerprints":{"codehealthFindingId/v1":"6cbe72d544305f8bf808dc379dd2e9fcdd8ad234c75ecca4c861e55dbc011756"}},{"ruleId":"D2","level":"warning","message":{"text":"StringExtensions.IsStartOfStringAcronym (cognitive 18): StringExtensions.IsStartOfStringAcronym has cognitive complexity 18 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/StringExtensions.cs"},"region":{"startLine":105}}}],"partialFingerprints":{"codehealthFindingId/v1":"9343626ca591023e0e0f43c6fb43ade4211d06b4c4ff0bebb78ceaf44e7d6181"}},{"ruleId":"D2","level":"warning","message":{"text":"BindingExtension.ProvideValue (cognitive 18): BindingExtension.ProvideValue has cognitive complexity 18 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/Markup/BindingExtension.cs"},"region":{"startLine":36}}}],"partialFingerprints":{"codehealthFindingId/v1":"ccf59aa0fcb0ce217ce08bf3e741bcf90a7c3b7433cffaeed759fd09ebdc71c3"}},{"ruleId":"D2","level":"warning","message":{"text":"User32.EnablePrivilege (cognitive 18): User32.EnablePrivilege has cognitive complexity 18 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Native/User32.cs"},"region":{"startLine":171}}}],"partialFingerprints":{"codehealthFindingId/v1":"3b4f66df84fb5b667394e48870bd7fed74b49c4fdd55d6bec9a7e819fe280ccc"}},{"ruleId":"D2","level":"warning","message":{"text":"MainViewModelBase.UpdateLibraryData (cognitive 18): MainViewModelBase.UpdateLibraryData has cognitive complexity 18 (threshold 15). Most of this is not in the body itself: 2 of the 18 points are its own statements and the rest belongs to one function literal inside it that branches (line 754). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/MainViewModelBase.cs"},"region":{"startLine":741}}}],"partialFingerprints":{"codehealthFindingId/v1":"a8685e6fbd0cefeb30012cf5dc0a80cafec598ccd70f7689196feecc90c22f87"}},{"ruleId":"D2","level":"warning","message":{"text":"SearchViewModel.TextBoxKeyUp (cognitive 18): SearchViewModel.TextBoxKeyUp has cognitive complexity 18 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":883}}}],"partialFingerprints":{"codehealthFindingId/v1":"6aed600af59c9d47fecd006f077ffc1877e7320eb1f06b3489e0fae3c5b5a493"}},{"ruleId":"D2","level":"warning","message":{"text":"GameMenu.InitializeItems (cognitive 18): GameMenu.InitializeItems has cognitive complexity 18 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs"},"region":{"startLine":461}}}],"partialFingerprints":{"codehealthFindingId/v1":"18a9c0da5eba002f4ab6832fc3141381a970283957c2da88f3920adbd1f2bcb6"}},{"ruleId":"D2","level":"warning","message":{"text":"GameEditViewModel.ConvertGameInfo (cognitive 18): GameEditViewModel.ConvertGameInfo has cognitive complexity 18 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelMetadata.cs"},"region":{"startLine":481}}}],"partialFingerprints":{"codehealthFindingId/v1":"ae66c12eacc43991e5f6764d3ddbaa8a5ae294e790775f272d2c558a47094e4a"}},{"ruleId":"D2","level":"warning","message":{"text":"ToolsConfigViewModel.AddAppFromExe (cognitive 18): ToolsConfigViewModel.AddAppFromExe has cognitive complexity 18 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/ToolsConfigViewModel.cs"},"region":{"startLine":182}}}],"partialFingerprints":{"codehealthFindingId/v1":"a22f2343771be67aae68d225c437f92c40954bea4665f7013e155fe988c74703"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenApplication.FullscreenApplication_PropertyChanged (cognitive 18): FullscreenApplication.FullscreenApplication_PropertyChanged has cognitive complexity 18 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/FullscreenApplication.cs"},"region":{"startLine":138}}}],"partialFingerprints":{"codehealthFindingId/v1":"858481ebe19c934d91d90f1eb4f2d861690d3ed835a4a8a0767b8cca2d07582b"}},{"ruleId":"D2","level":"warning","message":{"text":"Themes.PackageTheme (cognitive 18): Themes.PackageTheme has cognitive complexity 18 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Toolbox/Themes.cs"},"region":{"startLine":171}}}],"partialFingerprints":{"codehealthFindingId/v1":"5fc67f47dabc8d6ce16ec635f3061c7b691c4298a3917fdfa66e6a274352541d"}},{"ruleId":"D2","level":"warning","message":{"text":"MenuHelpers.GenerateMenuParents (cognitive 17): MenuHelpers.GenerateMenuParents has cognitive complexity 17 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuHelpers.cs"},"region":{"startLine":75}}}],"partialFingerprints":{"codehealthFindingId/v1":"201e6a14e46952d06b913a7805a74547306f414db6626f0380908ed2e05e5580"}},{"ruleId":"D2","level":"warning","message":{"text":"GameExtensions.GetRawExecutablePath (cognitive 17): GameExtensions.GetRawExecutablePath has cognitive complexity 17 (threshold 15). Of this number, 16 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/GameExtensions.cs"},"region":{"startLine":283}}}],"partialFingerprints":{"codehealthFindingId/v1":"fe4c0b1768c2ac5d9e787be81bf3b3b1c23e2beab796c433809473fd2d6f5482"}},{"ruleId":"D2","level":"warning","message":{"text":"GamesEditor.RemoveGame (cognitive 17): GamesEditor.RemoveGame has cognitive complexity 17 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":873}}}],"partialFingerprints":{"codehealthFindingId/v1":"d3189034aed1c2da7c3044bced92f1201a44acd7c26464ba6cdf8fdfe9500a9b"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionFactory.LoadScripts (cognitive 17): ExtensionFactory.LoadScripts has cognitive complexity 17 (threshold 15). Of this number, 16 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":322}}}],"partialFingerprints":{"codehealthFindingId/v1":"46f911339de7d9d072cde758777774ce9b5a4cfbd75e62fac16ee0d18d0bc675"}},{"ruleId":"D2","level":"warning","message":{"text":"Diagnostic.CreateDiagPackage (cognitive 17): Diagnostic.CreateDiagPackage has cognitive complexity 17 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Diagnostic.cs"},"region":{"startLine":60}}}],"partialFingerprints":{"codehealthFindingId/v1":"fd2ea68a357cd61c884836fa41dd36fff58d9abb1ecbc038cb207b514dfaa337"}},{"ruleId":"D2","level":"warning","message":{"text":"GameControllerManager.ShouldResendKey (cognitive 17): GameControllerManager.ShouldResendKey has cognitive complexity 17 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Input/GameController.cs"},"region":{"startLine":359}}}],"partialFingerprints":{"codehealthFindingId/v1":"3ab3a9702d8c9f800fc2ed9aa20101957bc6d90b2b5ebaae74687bc706edd387"}},{"ruleId":"D2","level":"warning","message":{"text":"DatabaseFieldsManagerViewModel.RemoveUnusedPlatforms (cognitive 17): DatabaseFieldsManagerViewModel.RemoveUnusedPlatforms has cognitive complexity 17 (threshold 15). To reduce it, break up the iteration: give each loop body a named function, and split a multi-phase loop into one function per phase so no single body carries the whole pipeline."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DatabaseFieldsManagerViewModel.cs"},"region":{"startLine":870}}}],"partialFingerprints":{"codehealthFindingId/v1":"2164316893139c1b6a1ac8be6a012510bcb8ec74c942611d592d028c769f2732"}},{"ruleId":"D2","level":"warning","message":{"text":"EmulatedGamesImportViewModel.ExcludeDirectories (cognitive 17): EmulatedGamesImportViewModel.ExcludeDirectories has cognitive complexity 17 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatedGamesImportViewModel.cs"},"region":{"startLine":577}}}],"partialFingerprints":{"codehealthFindingId/v1":"14ca7e0fd725314fc9087b5b6cb53853eb39ac0feb6305e87b8b91d79a37be03"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenTilePanel.MeasureOverride (cognitive 17): FullscreenTilePanel.MeasureOverride has cognitive complexity 17 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/FullscreenTilePanel.cs"},"region":{"startLine":239}}}],"partialFingerprints":{"codehealthFindingId/v1":"5f033cfc37f2a3113ae30f10ad2f144c39a00bbb270c528ed8fd1844e9269ab3"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenTilePanel.MakeVisible (cognitive 17): FullscreenTilePanel.MakeVisible has cognitive complexity 17 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/FullscreenTilePanel.cs"},"region":{"startLine":656}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac36ab94400a55673312ea8ee82db2c502362ef1d3893f5006b0bfb5afd8c4db"}},{"ruleId":"D2","level":"warning","message":{"text":"Addons.CheckAddonsForUpdate (cognitive 16): Addons.CheckAddonsForUpdate has cognitive complexity 16 (threshold 15). Of this number, 15 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Addons/Addons.cs"},"region":{"startLine":63}}}],"partialFingerprints":{"codehealthFindingId/v1":"7c548b1adf94c40b78bc6614f48a6ad791e58de5be61a4c1d5e8dec1ed824f92"}},{"ruleId":"D2","level":"warning","message":{"text":"StringExtensions.GetLevenshteinDistance (cognitive 16): StringExtensions.GetLevenshteinDistance has cognitive complexity 16 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/StringExtensions.cs"},"region":{"startLine":394}}}],"partialFingerprints":{"codehealthFindingId/v1":"52d47a2e16d6b7e785691c84b6e5556d34494d2636db53e148468da4ae1deaea"}},{"ruleId":"D2","level":"warning","message":{"text":"ExtensionFactory.GetManifestsFromPath (cognitive 16): ExtensionFactory.GetManifestsFromPath has cognitive complexity 16 (threshold 15). Of this number, 15 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":173}}}],"partialFingerprints":{"codehealthFindingId/v1":"2f67e23435a6206b7f5d1ed8f244f3ace5b3b7c92261f99d88121d2799ef948b"}},{"ruleId":"D2","level":"warning","message":{"text":"RandomGameSelectViewModel.PickGame (cognitive 16): RandomGameSelectViewModel.PickGame has cognitive complexity 16 (threshold 15). To reduce it, split the body: most of this score is breadth rather than depth \u2014 checks laid out side by side rather than stacked \u2014 so group the statements between the checks into named steps and move each step into its own function. Some of it IS depth: where a check sits inside another whose only job is to reach it, merge the two into one condition, and where an else follows a branch that already returns, drop the trailing else and let the rest of the body continue at one level."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/RandomGameSelectViewModel.cs"},"region":{"startLine":121}}}],"partialFingerprints":{"codehealthFindingId/v1":"02629861b2e615afe8d2d39eefc66711ad1cdffb34df7ef805d16190aeed8939"}},{"ruleId":"D2","level":"warning","message":{"text":"GameControllerManager.ProcessButtonState (cognitive 16): GameControllerManager.ProcessButtonState has cognitive complexity 16 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Input/GameController.cs"},"region":{"startLine":408}}}],"partialFingerprints":{"codehealthFindingId/v1":"a4c2a00b03d4e9de3d95cb28aaa4b3cea9ff9b734b565c80c60f1453b9800bd6"}},{"ruleId":"D2","level":"warning","message":{"text":"AppSoftware.CopyDiffTo (cognitive 16): AppSoftware.CopyDiffTo has cognitive complexity 16 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/AppSoftware.cs"},"region":{"startLine":147}}}],"partialFingerprints":{"codehealthFindingId/v1":"47a94bfa7c0f569afd378d39ac1f22e66898426b6af393662e8769b3bccb0815"}},{"ruleId":"D2","level":"warning","message":{"text":"GameAction.Equals (cognitive 16): GameAction.Equals has cognitive complexity 16 (threshold 15). To reduce it, split the body: this score is breadth rather than depth \u2014 many checks laid out side by side rather than nested inside one another, so inverting conditions into early returns has nothing left to flatten. Group the statements between the checks into named steps and move each step into its own function, so the body reads as a short sequence of named stages."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/GameAction.cs"},"region":{"startLine":324}}}],"partialFingerprints":{"codehealthFindingId/v1":"02c6a411e93adc15380bba10f731e9a346ac46bbcc764082d221d14f0133984f"}},{"ruleId":"D2","level":"warning","message":{"text":"DesktopAppViewModel.InitializeCommands (cognitive 16): DesktopAppViewModel.InitializeCommands has cognitive complexity 16 (threshold 15). Most of this is not in the body itself: 0 of the 16 points are its own statements and the rest belongs to 9 function literals inside it that branch (lines 150, 347, 372, \u2026). The decisions are inside those literals, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literals\u0027 work into a named function or method at the enclosing scope and have each literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel_Commands.cs"},"region":{"startLine":102}}}],"partialFingerprints":{"codehealthFindingId/v1":"731dba8eeced2c76d464f762ef89783f59b743acc4e0f85cc57c25ea88591158"}},{"ruleId":"D2","level":"warning","message":{"text":"EmulatedGamesImportViewModel.ImportGames (cognitive 16): EmulatedGamesImportViewModel.ImportGames has cognitive complexity 16 (threshold 15). Of this number, 15 points are the body\u0027s own statements and 1 belongs to one function literal inside it that branches. To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatedGamesImportViewModel.cs"},"region":{"startLine":466}}}],"partialFingerprints":{"codehealthFindingId/v1":"dd90af6c070d471ea5133b01cdc23c882014d4f671bc263d21741efbd9cc3ff3"}},{"ruleId":"D2","level":"warning","message":{"text":"InstalledGamesViewModel.ConfirmDialog (cognitive 16): InstalledGamesViewModel.ConfirmDialog has cognitive complexity 16 (threshold 15). To reduce it, split the body into named stages: move each independent step or branch into its own named function so the body reads as a short sequence of named calls rather than one long body."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/InstalledGamesViewModel.cs"},"region":{"startLine":299}}}],"partialFingerprints":{"codehealthFindingId/v1":"db38d6545289f4776c4fb7320d28ee75fea7e807f4cf2b9c70eadb5499781588"}},{"ruleId":"D2","level":"warning","message":{"text":"FullscreenApplication.SDLEventLoop (cognitive 16): FullscreenApplication.SDLEventLoop has cognitive complexity 16 (threshold 15). Most of this is not in the body itself: 0 of the 16 points are its own statements and the rest belongs to one function literal inside it that branches (line 305). The decisions are inside the literal, which nothing outside this body can call, review or test on its own, so splitting the enclosing body is not the move available here. To reduce it, lift the literal\u0027s work into a named function or method at the enclosing scope and have the literal call it, then reduce whichever part then reads as the largest."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/FullscreenApplication.cs"},"region":{"startLine":303}}}],"partialFingerprints":{"codehealthFindingId/v1":"7392f38456d38ac26989911069f6b4db9b12ba5ae0161dd7209a899eeb4b4a7e"}},{"ruleId":"D2","level":"warning","message":{"text":"DatParser.ParseGame (cognitive 16): DatParser.ParseGame has cognitive complexity 16 (threshold 15). To reduce it, flatten the nesting: invert conditions into early returns or guard clauses so the happy path stays at one level, and lift the deepest nested block into its own named function."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tools/Playnite.Utilities/DatParser.cs"},"region":{"startLine":68}}}],"partialFingerprints":{"codehealthFindingId/v1":"c530a18cdf2a7d74e0c235f3b941181a0af5a46792b645b573068a2680433ba2"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: SDL: TooManyMethods \u2014 4764 significant lines (blank, comment-only and punctuation-only lines excluded), 790 methods. The type holds no instance state, so there is no shared data to group its members by. To reduce it, split it by area instead: give each cohesive family of members its own smaller type, so no one type has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"b4447774eca694be5337d12e472006c05c8f6b4bb0a5147d56c6e8bdc092cae1"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Playnite/SDL2.cs: FileTooLong \u2014 5464 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"1dd69221a4bbb2d98268d98993342c6c0d35d7a7b54be123122faf7035f20053"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Common/TGASharpLib.cs: FileTooLong \u2014 2972 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"a94b82be648683e23b414355d319b6e492faf2d88765535f2f7149b316cb4bf9"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: PlayniteSettings: ClassTooLong \u2014 1322 significant lines (blank, comment-only and punctuation-only lines excluded), 23 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"c2459aa48a740390b9d726bf99a1c285eec5044b318665b9a25f562bd1bb258d"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: GameEditViewModel: TooManyMethods \u2014 1992 significant lines (blank, comment-only and punctuation-only lines excluded), 92 methods, declared across 3 files: ViewModels/GameEditViewModel.cs (74), ViewModels/GameEditViewModelMetadata.cs (15), ViewModels/GameEditViewModelFieldChecks.cs (3). To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"725434d2becf64b449b715c028232241568a28163643b016f45cb86744c74d83"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Settings/PlayniteSettings.cs: FileTooLong \u2014 1507 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"4770f335d803bb9b511143aed72f754d0793f83a4b76d30c09fa14508ee1b49a"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: Game: ClassTooLong \u2014 938 significant lines (blank, comment-only and punctuation-only lines excluded), 15 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"e89ff0db68ef3192cd8ee5f1c69518afe286b747ae405180908202dc14889f15"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: DesktopAppViewModel: TooManyMethods \u2014 1111 significant lines (blank, comment-only and punctuation-only lines excluded), 68 methods, declared across 4 files: ViewModels/DesktopAppViewModel.cs (63), ViewModels/DesktopAppViewModel_Sidebar.cs (3), ViewModels/DesktopAppViewModel_Commands.cs (1), ViewModels/DesktopAppViewModel_TopPanel.cs (1). To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"c844068213f5ceec1fec1a2f78183efac3cd8f88d7191f50b2aaeb0d18ab61db"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: GameDatabase: TooManyMethods \u2014 793 significant lines (blank, comment-only and punctuation-only lines excluded), 63 methods, declared across 2 files: Database/GameDatabase.cs (57), Database/GameDatabase_Filters.cs (6). To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac3ac2f3ac1eeb4efc45b11a6667074871d16f14a2189f04d82b3fb9a314d0b6"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Models/Game.cs: FileTooLong \u2014 1033 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"6bef319037febce5199629c716b987ed1bdb434dd46ab7eba75848b623d0b078"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Playnite/GamesEditor.cs: FileTooLong \u2014 983 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"e67cae406ef7d3c79327b50475ba0464b2f498b353cfb990c6e5f3742dc35eff"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: App/PlayniteApplication.cs: FileTooLong \u2014 939 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"c3116557297cf31d3aaf10c216365187883fdcd4541eed6196108469649dff63"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: OldModels/Ver2.cs: FileTooLong \u2014 869 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/OldModels/Ver2.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"678e7bb1d4440da9783a32191694e07d4b01bcb74812b11bfa8656a7a7909bdf"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Emulators/Scanner.cs: FileTooLong \u2014 851 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac8f109d0c59bcf845a3223c332611db7d02cd41e77b1f4141bd1ac2ed100a68"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Database/GameDatabase.cs: FileTooLong \u2014 849 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"f0d1d9c5f3285d514249369d573a26ce6bb111210ab00d09d5165daab5394160"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/GameEditViewModel.cs: FileTooLong \u2014 824 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"26c18e3bfd91bba5d4827981237027945a166e3fcd78e57d0f7b25514be002b3"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: FullscreenAppViewModel: TooManyMethods \u2014 845 significant lines (blank, comment-only and punctuation-only lines excluded), 48 methods, declared across 2 files: ViewModels/FullscreenAppViewModel.cs (47), ViewModels/FullscreenAppViewModel_Commands.cs (1). To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"bd22f18dfff33cb51c449af5784845ec29b996c0e766925dc2c1c8ed305c9864"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: GameScanner: ClassTooLong \u2014 622 significant lines (blank, comment-only and punctuation-only lines excluded), 15 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Emulators/Scanner.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ce792d392b7c2e799761f98be596269a4c9bd2a48fb3b5d8d5542128ca7cd736"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Settings/FilterSettings.cs: FileTooLong \u2014 767 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ac13ced06a4d836a75422f5727c57ecd7516f71545d0a7dcead7a45f67467de6"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: GamesEditor: TooManyMethods \u2014 929 significant lines (blank, comment-only and punctuation-only lines excluded), 46 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/GamesEditor.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"fc807b9d3baf41551fa609d0cc523e89b733b86a4e58467c8dad38f60d95fc97"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: PlayniteApplication: TooManyMethods \u2014 907 significant lines (blank, comment-only and punctuation-only lines excluded), 46 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"1afc79f81c392bb6e6abe55598d81c34a124aa5ee887806d77ba44f698164097"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/DesktopAppViewModel.cs: FileTooLong \u2014 760 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"b08873c7a7b6a2cfad23c27901cc3323ca209fca8e95a8c00fac15852a942e3a"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/GameEditViewModelFieldChecks.cs: FileTooLong \u2014 725 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModelFieldChecks.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"e3060c33ced8b3f086a6f8952e5fa14e4f3c717f73eeea83043877ab7680be33"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: FileSystem: TooManyMethods \u2014 280 significant lines (blank, comment-only and punctuation-only lines excluded), 40 methods, declared across 2 files: Common/FileSystem.cs (35), Common/FileSystem_Checksum.cs (5). The type holds no instance state, so there is no shared data to group its members by. To reduce it, split it by area instead: give each cohesive family of members its own smaller type, so no one type has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/FileSystem.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"5de780fea9254929eead5e4abdf41a85d661c38616ef3694e26dc61b3edccdf5"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/FullscreenAppViewModel.cs: FileTooLong \u2014 659 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"1a4aadfdbe893239853dc9ebb57fdd0c30333acd60da54699aa8b7eaf8c82f6d"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: DatabaseExplorer: ClassTooLong \u2014 509 significant lines (blank, comment-only and punctuation-only lines excluded), 21 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"261b6f811c9806d72e3168fc210fc46ad09ae1fc39953be5f0d80ec995b72d71"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: ItemCollection: TooManyMethods \u2014 300 significant lines (blank, comment-only and punctuation-only lines excluded), 38 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/ItemCollection.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"7f76fed60c5f9cde287fd701ee89132261dbb2e1502d51580cea8ef23dd49329"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: MainViewModelBase: TooManyMethods \u2014 552 significant lines (blank, comment-only and punctuation-only lines excluded), 37 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/MainViewModelBase.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"4efd161ba2ae3842f2a84dc6daa113d915689f550067fa96b9be07d5aa0bfc0c"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: FullscreenTilePanel: TooManyMethods \u2014 404 significant lines (blank, comment-only and punctuation-only lines excluded), 37 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/FullscreenTilePanel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"1d9d7033f6a9686d543b1b14cb827a00d4b5ad7decc9ff32069d7e26a651bc8d"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: Plugin: TooManyMethods \u2014 81 significant lines (blank, comment-only and punctuation-only lines excluded), 37 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Plugins/Plugin.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ae94dffb51a8dac7993ec68e33b896bf068be1cc2f321b85a0af90f54adaa828"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: GameOverview: ClassTooLong \u2014 484 significant lines (blank, comment-only and punctuation-only lines excluded), 16 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Views/GameOverview.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"9601dea2e6be1cf0e01599b5748972209a679cda0a30a64d60d815d0e52e9cd7"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Database/DatabaseExplorer.cs: FileTooLong \u2014 592 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"61a53283ce0c140c549061cb1738eb67c52b25f325a9b655e462c57d008df115"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: DatabaseFieldsManagerViewModel: ClassTooLong \u2014 467 significant lines (blank, comment-only and punctuation-only lines excluded), 20 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DatabaseFieldsManagerViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"747fa42858b57f7cebcdda80cc6e4f9430ffd562c825d221c8a42b5c1668d3c4"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/MainViewModelBase.cs: FileTooLong \u2014 580 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/MainViewModelBase.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"004774aa592a9f1161b516313954cc0c63e3d665ea881031cdbe39d69930a637"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: ViewModels/SearchViewModel.cs: FileTooLong \u2014 579 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"ae790cea498a17cb7c83325ca8c987a8fe581300b282488e69f96ee8ef1f1b0c"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: GenericPlayController: ClassTooLong \u2014 461 significant lines (blank, comment-only and punctuation-only lines excluded), 13 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"cf563b6c1b7bf09ca905271825a21d932373498b9cb97a1b2b230be5e49547ed"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: FilterMatcher: TooManyMethods \u2014 159 significant lines (blank, comment-only and punctuation-only lines excluded), 34 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase_Filters.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"8ac3d3fe8f827a1c0bcad0834e056453107013717d16a8be07f6687062d539d1"}},{"ruleId":"D3","level":"warning","message":{"text":"ClassTooLong: AddonsViewModel: ClassTooLong \u2014 449 significant lines (blank, comment-only and punctuation-only lines excluded), 14 methods, declared across 2 files: ViewModels/AddonsViewModel.cs (11), ViewModels/AddonsViewModel_Online.cs (3). To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"8b6ebcbfd48083903e3ca947ea4292823036779fc3e5f32dec996f3aeefa6f9b"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: TGA: TooManyMethods \u2014 814 significant lines (blank, comment-only and punctuation-only lines excluded), 33 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/TGASharpLib.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"41ef39bcf015646753186d6614ffe10181656e2cb6d7a4d30b1b16940a75d8d2"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: FilterSettings: TooManyMethods \u2014 625 significant lines (blank, comment-only and punctuation-only lines excluded), 31 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/FilterSettings.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"9b06b1ec8ebb4b6362f5f0bdde2027363b8180070b44aaa3eab9782903cda484"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: ExtensionFactory: TooManyMethods \u2014 422 significant lines (blank, comment-only and punctuation-only lines excluded), 31 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"81e71f46d291d044608f876cc1317bdb87950aadd1d31b314c15eda2dc4e0cd7"}},{"ruleId":"D3","level":"warning","message":{"text":"TooManyMethods: InMemoryGameDatabase: TooManyMethods \u2014 105 significant lines (blank, comment-only and punctuation-only lines excluded), 31 methods. To reduce it, group the members that share the same data into a smaller type of their own and delegate to it, so no single type carries every responsibility."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/InMemoryGameDatabase.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"c88500f20ebddb1f053627d84fd18cc1929b7cbf6aaf58bb0a253f11cd29baab"}},{"ruleId":"D3","level":"warning","message":{"text":"FileTooLong: Views/GameOverview.cs: FileTooLong \u2014 507 significant lines (blank, comment-only and punctuation-only lines excluded). To reduce it, split the file along the responsibilities already in it: move each cohesive group of declarations into its own sibling file in the same module or package, so no one file has to be read whole to change one of them."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Views/GameOverview.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"cfc0101495c9d96941b171d5b5111db95afcdd2694a15f5cbb1fb664a256319a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (21 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs:1671-1691 | source/Playnite.DesktopApp/ViewModels/SettingsViewModel.cs:692-712 \u2014 the copies sit in sibling files of one directory: extract the block into a single shared function in that directory and call it from each site, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs:1671\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":1671}}}],"partialFingerprints":{"codehealthFindingId/v1":"029007aa459c6706a6f9a6977e4be240c6438cc00e772cd1af8634691edc6bc4"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (20 lines \u00D7 2): source/Playnite.DesktopApp/ProgramEntry.cs:50-69 | source/Playnite.FullscreenApp/ProgramEntry.cs:50-69 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ProgramEntry.cs"},"region":{"startLine":50}}}],"partialFingerprints":{"codehealthFindingId/v1":"28d9287c428245c4737a9b11c23e815284009ce048271599d4642fe01fb991c9"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (18 lines \u00D7 2): source/Playnite/ObservablePowerStatus.cs:76-93 | source/Playnite/ObservableTime.cs:33-50 \u2014 the copies sit in sibling files of one directory: extract the block into a single shared function in that directory and call it from each site, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/ObservablePowerStatus.cs:76\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ObservablePowerStatus.cs"},"region":{"startLine":76}}}],"partialFingerprints":{"codehealthFindingId/v1":"9a4475c692bd296ae968fa1fbbc154c46f6ec360cd15e4ce4fce9a029f29b47a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (18 lines \u00D7 2): source/Playnite.DesktopApp/DesktopApplication.cs:375-392 | source/Playnite.FullscreenApp/FullscreenApplication.cs:280-297 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopApplication.cs"},"region":{"startLine":375}}}],"partialFingerprints":{"codehealthFindingId/v1":"a46c97f8668ad37e871d430b6757491a7bfd32b104ef9f753ba2a4f1aaa27536"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (18 lines \u00D7 2): source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs:206-223 | source/Playnite.FullscreenApp/Windows/TextInputWindow.xaml.cs:151-168 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs:206\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs"},"region":{"startLine":206}}}],"partialFingerprints":{"codehealthFindingId/v1":"4cc7c03f112d5bce69e615b1936a1528515862b83901a1cdd61a52dcf392b508"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (18 lines \u00D7 2): source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs:352-369 | source/Playnite.FullscreenApp/Windows/MessageBoxWindow.xaml.cs:245-262 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs:352\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Windows/MessageBoxWindow.xaml.cs"},"region":{"startLine":352}}}],"partialFingerprints":{"codehealthFindingId/v1":"b02f023e4df5687137f5c88852fc43b5cc3afebe41497633af3176f178c3081c"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (17 lines \u00D7 2): source/Playnite/Database/OldModels/Ver2.cs:89-105 | source/PlayniteSDK/Models/DatabaseObject.cs:54-70 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/OldModels/Ver2.cs"},"region":{"startLine":89}}}],"partialFingerprints":{"codehealthFindingId/v1":"4d5a5c11c4e4fdde3da0a9d386e69b0a356655e9e062853ff3353e9c0577f9a9"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (17 lines \u00D7 2): source/Playnite/App/PlayniteApplication.cs:1605-1621 | source/Playnite/App/PlayniteApplication.cs:1649-1665 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/App/PlayniteApplication.cs:1605\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":1605}}}],"partialFingerprints":{"codehealthFindingId/v1":"0b1324620dbadb395242cd36dc761972eab28db5805d79d83c1b5d1a36777144"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (17 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs:380-396 | source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs:406-422 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs:380\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs"},"region":{"startLine":380}}}],"partialFingerprints":{"codehealthFindingId/v1":"fefe64f5446a8ea0bf4625cf95b6e460ea275b592de91edbf5835f0d11acb7f5"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (16 lines \u00D7 2): source/Playnite/Converters/ListToStringConverter.cs:146-161 | source/Playnite/Converters/ListToStringConverter.cs:195-210 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Converters/ListToStringConverter.cs:146\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Converters/ListToStringConverter.cs"},"region":{"startLine":146}}}],"partialFingerprints":{"codehealthFindingId/v1":"325504d9402b4951c854ee943c080827148d894057ba4fd2e7ccf7b77872b15c"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (16 lines \u00D7 2): source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs:266-281 | source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs:288-303 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs:266\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names \u2014 the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel_Commands.cs"},"region":{"startLine":266}}}],"partialFingerprints":{"codehealthFindingId/v1":"d0b1722be92874809836eb6f87d766c57436fa30370a8547a513f5210d24759f"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15 lines \u00D7 2): source/PlayniteSDK/Extensions/ListExtensions.cs:118-132 | source/PlayniteSDK/Extensions/ListExtensions.cs:149-163 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/PlayniteSDK/Extensions/ListExtensions.cs:118\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names \u2014 the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Extensions/ListExtensions.cs"},"region":{"startLine":118}}}],"partialFingerprints":{"codehealthFindingId/v1":"3d9299ddae99afb822fdd88745c03e65ee5559aa80da5e9c5e112011b68c9a7a"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/GameDetailsViewModel.cs:104-118 | source/Playnite.FullscreenApp/ViewModels/GameDetailsViewModel.cs:47-61 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/GameDetailsViewModel.cs:104\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameDetailsViewModel.cs"},"region":{"startLine":104}}}],"partialFingerprints":{"codehealthFindingId/v1":"ea79bd6d0890cfe58f4c692f6dfb8dd6821ccf2fb8c894cd23c03dba77d61345"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (15 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs:396-410 | source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs:947-961 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs:396\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":396}}}],"partialFingerprints":{"codehealthFindingId/v1":"4888dd459b9555b8f8308b746ebef541523f05315264ea70122e6e5eff63c2be"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 3): source/Playnite/Controllers/GenericGameController.cs:550-563 | source/Playnite/Controllers/GenericGameController.cs:583-596 | source/Playnite/Controllers/GenericGameController.cs:633-646 \u2014 all 3 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Controllers/GenericGameController.cs:550\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":550}}}],"partialFingerprints":{"codehealthFindingId/v1":"8dec7120dbbe1089267cb0bbe4b443d727f6b831f86c5a831c8063c7aea5bcb0"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite/Controllers/GenericGameController.cs:566-579 | source/Playnite/Controllers/GenericGameController.cs:600-613 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Controllers/GenericGameController.cs:566\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":566}}}],"partialFingerprints":{"codehealthFindingId/v1":"87d93ae38d402a48d305c5bb157385bd667351a04e4753eb051671310e1137ad"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/PlayniteSDK/Extensions/ListExtensions.cs:200-213 | source/PlayniteSDK/Extensions/ListExtensions.cs:266-279 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/PlayniteSDK/Extensions/ListExtensions.cs:200\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Extensions/ListExtensions.cs"},"region":{"startLine":200}}}],"partialFingerprints":{"codehealthFindingId/v1":"e9b03e8073bb038da722fdcda9110f34e485d53182fb958cc818deb544606f73"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs:491-504 | source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs:507-520 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs:491\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs"},"region":{"startLine":491}}}],"partialFingerprints":{"codehealthFindingId/v1":"9cf51a50c8a04e907c2806f96376e79079e9998bd37230fb5c3ffe82ee40d4c7"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs:127-140 | source/Playnite.FullscreenApp/Controls/FilterEnumListSelection.cs:132-145 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs:127\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs"},"region":{"startLine":127}}}],"partialFingerprints":{"codehealthFindingId/v1":"027bf3cdc446dc538bc6e8ccc6ada901638a4cd5b1c3e0db31f3c803e92245a2"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite.DesktopApp/Controls/FilterStringSelectionBox.cs:88-101 | source/Playnite.FullscreenApp/Controls/FilterStringListSelection.cs:116-129 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/FilterStringSelectionBox.cs:88\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/FilterStringSelectionBox.cs"},"region":{"startLine":88}}}],"partialFingerprints":{"codehealthFindingId/v1":"45e5a27ba392a13647857d63f35bbdfbbec2cf7dd86f5703f2ab7234489195ef"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:54-67 | source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:103-116 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:54\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs"},"region":{"startLine":54}}}],"partialFingerprints":{"codehealthFindingId/v1":"cedbfbce44729289fb500a5488665ceeaa0de77cba5010e8fc734ef5090bd1c0"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (14 lines \u00D7 2): source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:72-85 | source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:121-134 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs:72\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/ItemsControlEx.cs"},"region":{"startLine":72}}}],"partialFingerprints":{"codehealthFindingId/v1":"6a243a57000d4562c21bf3da3cf27c0b1fb87173d158092ae34cc551446ddd77"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): source/Playnite.DesktopApp/Controls/FilterSelectionBox.cs:154-167 | source/Playnite.FullscreenApp/Controls/FilterDbItemtSelection.cs:118-130 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/FilterSelectionBox.cs:154\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/FilterSelectionBox.cs"},"region":{"startLine":154}}}],"partialFingerprints":{"codehealthFindingId/v1":"ae8e86e04a89c04504d77863da1828ae3c6f1706f1cc97b825cbfdac3e1df445"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): source/Playnite.DesktopApp/DesktopCollectionView.cs:576-588 | source/Playnite.FullscreenApp/FullscreenCollectionView.cs:87-99 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/DesktopCollectionView.cs:576\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopCollectionView.cs"},"region":{"startLine":576}}}],"partialFingerprints":{"codehealthFindingId/v1":"0c3421ba8e18e2804f4a19a5f712bec1a37d62fdc9696893fd3f11e972b03f12"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/DesignData/DesignMainViewModel.cs:66-78 | source/Playnite.FullscreenApp/ViewModels/DesignData/DesignMainViewModel.cs:74-86 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesignData/DesignMainViewModel.cs"},"region":{"startLine":66}}}],"partialFingerprints":{"codehealthFindingId/v1":"925f432cbfecd913dd36e1809dc7d84bacba9c8bfe3bb2a0e11751e2f6c370ec"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs:1611-1623 | source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs:422-434 \u2014 the copies sit in sibling files of one directory: extract the block into a single shared function in that directory and call it from each site, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs:1611\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":1611}}}],"partialFingerprints":{"codehealthFindingId/v1":"8aa3a8fe778b807f92a8e045081792aa0f4711e16d23850272724de56a856a70"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (13 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs:1002-1014 | source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs:1165-1177 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs:1002\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":1002}}}],"partialFingerprints":{"codehealthFindingId/v1":"aafb98df17ee9e69a017287d24074137bb3f021c615778c89a612764a8efda61"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (12 lines \u00D7 2): source/Playnite/Themes.cs:241-252 | source/Playnite/Themes.cs:266-277 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Themes.cs:241\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Themes.cs"},"region":{"startLine":241}}}],"partialFingerprints":{"codehealthFindingId/v1":"0fb75040f24d8a3315496f10ae70aca143433f9116620509e88c422f3d260c6e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (12 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs:369-380 | source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs:393-404 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs:369\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/MetadataComparisonViewModel.cs"},"region":{"startLine":369}}}],"partialFingerprints":{"codehealthFindingId/v1":"334bb707a76377fa3dbf47411feff70c19f659037eb6113000d0e5b8bf7e2d40"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 2): source/Playnite/Controllers/GenericGameController.cs:290-300 | source/Playnite/Controllers/GenericGameController.cs:306-316 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Controllers/GenericGameController.cs:290\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names \u2014 the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":290}}}],"partialFingerprints":{"codehealthFindingId/v1":"736e187809fa340157930358e589775b02474a5038cf6ec48e0633e1654e1aee"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (11 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs:397-407 | source/Playnite.DesktopApp/ViewModels/LibraryIntegrationsViewModel.cs:133-143 \u2014 the copies sit in sibling files of one directory: extract the block into a single shared function in that directory and call it from each site, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs:397\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs"},"region":{"startLine":397}}}],"partialFingerprints":{"codehealthFindingId/v1":"b69b26ab63cbbdfb4532767fd9df491b0d305c78797634634aa57d7e2f20d570"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): source/Playnite/Database/Collections/RegionsCollection.cs:60-69 | source/Playnite/Database/Collections/RegionsCollection.cs:113-122 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Database/Collections/RegionsCollection.cs:60\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/RegionsCollection.cs"},"region":{"startLine":60}}}],"partialFingerprints":{"codehealthFindingId/v1":"91f34a27c621f020c14f10a232a1dab7e1b7762fce014c7466e784788a48d32c"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): source/Playnite/Database/Collections/PlatformsCollection.cs:133-142 | source/Playnite/Database/Collections/PlatformsCollection.cs:186-195 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Database/Collections/PlatformsCollection.cs:133\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/PlatformsCollection.cs"},"region":{"startLine":133}}}],"partialFingerprints":{"codehealthFindingId/v1":"1aae437084ce6037cf4ba3c5c66abcc7d91b9b13cdf51b0c5f91b01a0cf07be5"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (10 lines \u00D7 2): source/PlayniteSDK/Models/Emulator.cs:765-774 | source/PlayniteSDK/Models/Emulator.cs:789-798 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/PlayniteSDK/Models/Emulator.cs:765\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Emulator.cs"},"region":{"startLine":765}}}],"partialFingerprints":{"codehealthFindingId/v1":"f51abb6440e16580e2f4a195b7a9f10e089f845a9730cad51dde8a6c8d12b0c1"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): source/Playnite/Backup.cs:283-291 | source/Playnite/Backup.cs:324-332 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Backup.cs"},"region":{"startLine":283}}}],"partialFingerprints":{"codehealthFindingId/v1":"1ccc1773bab3c5209eec74bc1f77ffeda07f21e7e0f98b67c0bc8401696cafbe"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): source/Playnite/MenuItems.cs:269-277 | source/Playnite/MenuItems.cs:297-305 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/MenuItems.cs:269\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names \u2014 the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuItems.cs"},"region":{"startLine":269}}}],"partialFingerprints":{"codehealthFindingId/v1":"0fba94e9237e9ce12ced25db42db1b7475c06cca1be1453c517ad7373e2725b2"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): source/Playnite/Settings/PlayniteSettings.cs:2339-2347 | source/Playnite/Settings/PlayniteSettings.cs:2382-2390 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":2339}}}],"partialFingerprints":{"codehealthFindingId/v1":"35bac5d9cc251f65e1e95fc1b7d607bf909e39d27f5785813d21736aa6dde7d3"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): source/Playnite.DesktopApp/Controls/ComboBoxList.cs:130-138 | source/Playnite.DesktopApp/Controls/FilterSelectionBox.cs:36-44 \u2014 the copies sit in sibling files of one directory: extract the block into a single shared function in that directory and call it from each site, so a change lands once. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/ComboBoxList.cs:130\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/ComboBoxList.cs"},"region":{"startLine":130}}}],"partialFingerprints":{"codehealthFindingId/v1":"89794f79e71cbe28c5b376fd38510001ab40403dfcf68441b51bfb3b449de6c4"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (9 lines \u00D7 2): source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs:70-78 | source/Playnite.FullscreenApp/Controls/FilterEnumListSelection.cs:76-84 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs:70\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that. Note that the copies do not run to the end of the range shown: their LAST lines are different code, not the same code under different names \u2014 the matched region ends inside that line. Extract the lines above it, and read the last line of each site separately."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/FilterEnumSelectionBox.cs"},"region":{"startLine":70}}}],"partialFingerprints":{"codehealthFindingId/v1":"65b6e51d1ff962468557439b4ed88c66645c4c3b195d80ec5c460841f289f04f"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (8 lines \u00D7 2): source/Playnite/MenuItems.cs:38-45 | source/Playnite.DesktopApp/Controls/Menus/GameMenu.cs:465-472 \u2014 the copies span different directories, so extracting a shared function means choosing where it lives: put it somewhere both call sites can already reach \u2014 a location they all depend on today, or a new shared one if there is none \u2014 and call it from each site; until then, every change has to be made twice. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/MenuItems.cs:38\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/MenuItems.cs"},"region":{"startLine":38}}}],"partialFingerprints":{"codehealthFindingId/v1":"608c72c3d5724228ab54251b33955dd85298554a2e1f247fdf04bfd5b71d1b8e"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (7 lines \u00D7 4): source/Playnite/Diagnostic.cs:225-231 | source/Playnite/Diagnostic.cs:232-238 | source/Playnite/Diagnostic.cs:239-245 | source/Playnite/Diagnostic.cs:246-252 \u2014 all 4 copies are in the same file, so extract the block into one function there and call it from every one of those sites \u2014 resolving only two of them leaves the rest to drift apart the first time one is edited. The matched lines also transfer control out of the body holding them, which cannot survive a move into a called unit unchanged: have the extracted unit return that decision and let each site act on it."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Diagnostic.cs"},"region":{"startLine":225}}}],"partialFingerprints":{"codehealthFindingId/v1":"c2df84ad249a711b048f6cfaa8b72227007bf1d17456c2360b9f68dad85c9455"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (6 lines \u00D7 2): source/Playnite/Extensions/GameExtensions.cs:202-207 | source/Playnite/Extensions/GameExtensions.cs:210-215 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite/Extensions/GameExtensions.cs:202\u0060 it does not close everything it opens, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/GameExtensions.cs"},"region":{"startLine":202}}}],"partialFingerprints":{"codehealthFindingId/v1":"235735f2fd416894c66af1e7e354e5d5bb526cd16023fde4bbe72a04547aebcc"}},{"ruleId":"D4","level":"warning","message":{"text":"Duplicated block (5 lines \u00D7 2): source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs:235-239 | source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs:245-249 \u2014 both copies are in the same file, so extract the block into one function there and call it from each site \u2014 the copies drift apart the first time only one of them is edited. Read the line range as the matched WINDOW rather than a finished unit: at \u0060source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs:235\u0060 it begins part-way through the construct above it, so those exact lines cannot be lifted as they stand \u2014 widen the region to the smallest complete statement or declaration that contains it, and extract that."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/AddonsViewModel.cs"},"region":{"startLine":235}}}],"partialFingerprints":{"codehealthFindingId/v1":"1079de47c5cf0a80308ad8f625edd31bedd29041a39bbd0ce1cb08179bc94581"}},{"ruleId":"D5","level":"warning","message":{"text":"Off the main sequence: Playnite.SDK: Playnite.SDK: abstractness 0.23, instability 0.00, distance 0.77 \u2014 zone of pain \u2014 concrete and depended on by 4 project(s), so it\u0027s rigid to change."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"da479952c110c00d4345988c92f384d9a86835edc436540bca5bb310b9dce0fb"}},{"ruleId":"D5","level":"warning","message":{"text":"Off the main sequence: Playnite: Playnite: abstractness 0.04, instability 0.20, distance 0.76 \u2014 zone of pain \u2014 concrete and depended on by 4 project(s), so it\u0027s rigid to change."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"9b333c6a0bd5cb8153c33cc32f40285dab47b6842c9ec1afbbd2252fa82f6b67"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: Plugin (LCOM4 8): Plugin\u0027s methods form 8 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Plugins/Plugin.cs"},"region":{"startLine":168}}}],"partialFingerprints":{"codehealthFindingId/v1":"f3a2b31339292a4d93893bfd630947e40121db4dcc274d7433d800544bde80a8"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: PlayniteSettings (LCOM4 7): PlayniteSettings\u0027s methods form 7 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Settings/PlayniteSettings.cs"},"region":{"startLine":261}}}],"partialFingerprints":{"codehealthFindingId/v1":"f3afa8c2e81162a95924c71c7e2f90b2a06ee48fc4568048bc76defeabcd4db4"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: FullscreenAppViewModel (LCOM4 6): FullscreenAppViewModel\u0027s methods form 6 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":35}}}],"partialFingerprints":{"codehealthFindingId/v1":"b26643d4c6437cffbd25814c8fa74362f190402197190ef8105226bb58456b93"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: Game (LCOM4 6): Game\u0027s methods form 6 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Models/Game.cs"},"region":{"startLine":188}}}],"partialFingerprints":{"codehealthFindingId/v1":"91bcc55e0af0854444cc16ae6ff860ed3b69ead32032d29e261800b8894f2194"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: DatabaseFieldsManagerViewModel (LCOM4 5): DatabaseFieldsManagerViewModel\u0027s methods form 5 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DatabaseFieldsManagerViewModel.cs"},"region":{"startLine":23}}}],"partialFingerprints":{"codehealthFindingId/v1":"532822646d548a447501258e229f431e51e2b96b47075721b30775e6e18ee95f"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: DesktopAppViewModel (LCOM4 5): DesktopAppViewModel\u0027s methods form 5 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs"},"region":{"startLine":40}}}],"partialFingerprints":{"codehealthFindingId/v1":"f6860f7dc56d3d92be0e05e012deb85f01ab83e461688026e05bccd5bd4047db"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: ExtensionFactory (LCOM4 5): ExtensionFactory\u0027s methods form 5 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":65}}}],"partialFingerprints":{"codehealthFindingId/v1":"4da8aafe898e31fe4ea023d761e0665071faf5adf1a32232237c904b5d2f37ee"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: EmulatorsViewModel (LCOM4 4): EmulatorsViewModel\u0027s methods form 4 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs"},"region":{"startLine":25}}}],"partialFingerprints":{"codehealthFindingId/v1":"5b2a376b32fa38a9a6d45e7de3e911a77703a0aa40f301b808e7b8516ffaf8c1"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: PlayniteApiRoot (LCOM4 4): PlayniteApiRoot\u0027s methods form 4 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/API/PlayniteAPI.cs"},"region":{"startLine":38}}}],"partialFingerprints":{"codehealthFindingId/v1":"b8f160177f1b5770b384fb548bd9a1dc8b6256c4c9c4784d4e97fe69b9da6b6c"}},{"ruleId":"D6","level":"warning","message":{"text":"Low cohesion: WindowBase (LCOM4 4): WindowBase\u0027s methods form 4 groups that share no state and don\u0027t call each other \u2014 a sign it may have several responsibilities. Review whether it splits into focused classes."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controls/WindowBase.cs"},"region":{"startLine":46}}}],"partialFingerprints":{"codehealthFindingId/v1":"3c7074972f7e2c362e1a45ac715b93b38d4e74c36c554118c439bd01b4630df8"}},{"ruleId":"D10","level":"error","message":{"text":"No assertions (empty test): GetFileEntriesTest: Test method has an empty body \u2014 it asserts nothing and exercises no code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.Tests/CueSheetTests.cs"},"region":{"startLine":15}}}],"partialFingerprints":{"codehealthFindingId/v1":"5152b1e2fc97d071946b0f7c3b15b867329cc7f1a37c2e4101dcae7423e628dd"}},{"ruleId":"D10","level":"error","message":{"text":"No assertions (empty test): ViewSettingsTest: Test method has an empty body \u2014 it asserts nothing and exercises no code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.DesktopApp.Tests/MainViewAPITests.cs"},"region":{"startLine":19}}}],"partialFingerprints":{"codehealthFindingId/v1":"2e74f7b1dcb151738ce6f0ec6e3d2345cc48091ddcff88b8b83f3429245eff32"}},{"ruleId":"D11","level":"warning","message":{"text":"Test reliability not measured \u2014 no test run produced results: Test reliability NOT MEASURED: the test run produced no results for any test tier, so no test ever ran and flakiness could not be exercised. The cause could not be attributed, so it is excluded from the score rather than read as an absence of tests."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"7d83a505f7fa19aeeece76141ae1e468d77e2a3fea2e88604b8140ebad47a6fe"}},{"ruleId":"D16","level":"note","message":{"text":"Off-boarding risk: anonymized user #1: If anonymized user #1 becomes unavailable, 54 significant file(s) lose their only recent owner: source/Playnite/Settings/PlayniteSettings.cs, source/Playnite/App/PlayniteApplication.cs, source/Playnite/Database/GameDatabase.cs, source/Playnite/Emulators/Scanner.cs, source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel.cs, source/Playnite/ViewModels/SearchViewModel.cs, source/Playnite/ViewModels/MainViewModelBase.cs, source/Playnite/Controllers/GenericGameController.cs (\u002B46 more). Pair on, review, or document these before any departure."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"1b6a2503fc3d3a91ecb63d97584009e4e8d5245b3510adbd73f5d79d8e88deb4"}},{"ruleId":"D16","level":"note","message":{"text":"Further sole-owners (lower concentration): 2 other contributor(s) are each the sole owner of a small amount of code below the off-boarding threshold \u2014 folded into the bus-factor score and metrics (56 single-owned of 298 analysed files in total, counted over production source files of roughly 100 lines or more, excluding tests, vendored, generated and example/demo trees, largest first). They are anonymized user #2 (1 file(s)), anonymized user #3 (1 file(s)) \u2014 spread or document their files in the same way, at lower priority than the named off-boarding risks above."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"6eac528f2429e724e1a97ed868f79eefbcf1888dab4af9a9e673429369bb5b2f"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 4 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/SliderWithPopup.xaml.cs"},"region":{"startLine":44}}}],"partialFingerprints":{"codehealthFindingId/v1":"505d9a98cc2eabc4d4a046d2789a8a22bcbe0b5829e2722c24370224ba945e58"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 4 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/Controls/SliderWithPopup.xaml.cs"},"region":{"startLine":60}}}],"partialFingerprints":{"codehealthFindingId/v1":"58d65fd32cf4aae67cbfbd6c56de2380a0045615ef475f282949bac79dfd58ed"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 4 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs"},"region":{"startLine":348}}}],"partialFingerprints":{"codehealthFindingId/v1":"165f1d5c1e75649f1ab239c16af99bfedf2d4fcffeed4e56f18b4b9991a24c06"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 4 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.FullscreenApp.Tests/Controls/FullscreenTilePanelTests.cs"},"region":{"startLine":30}}}],"partialFingerprints":{"codehealthFindingId/v1":"e169c0cccbe0370db6ad255f535933430f351e0bb7d9e55be5e90ed72d5ba2e0"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 4 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/TestPlugin/TestPluginSettings.cs"},"region":{"startLine":45}}}],"partialFingerprints":{"codehealthFindingId/v1":"c98edae02305910f8248c75f05a111d33f4c8b638b64e3386db6b08bcfbc8eff"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO test db path recovery \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopApplication.cs"},"region":{"startLine":240}}}],"partialFingerprints":{"codehealthFindingId/v1":"8cea1b7a65c7cf9b258759fc423ba8cce03957e59ead0b9a14c096e061db6ca8"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS4014 \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/DesktopApplication.cs"},"region":{"startLine":93}}}],"partialFingerprints":{"codehealthFindingId/v1":"2ae6cde0ac66bb2cbb01cf2bb944c41f411ecb141b1d2ba3b58e7ebfcdf04a77"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS4014 \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/DesktopAppViewModel_Commands.cs"},"region":{"startLine":134}}}],"partialFingerprints":{"codehealthFindingId/v1":"54851ac8ee5ec69f8e7de108dd9fa1df51a5904b586c9eb6c23402db1082e15e"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS4014 \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/InstalledGamesViewModel.cs"},"region":{"startLine":280}}}],"partialFingerprints":{"codehealthFindingId/v1":"113b4150f0dcbd0edcc21d41c344f22a327b8ca263d5a687d7d8e7ec117aa1a1"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO rewrite to something more sane \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/EmulatorsViewModel.cs"},"region":{"startLine":625}}}],"partialFingerprints":{"codehealthFindingId/v1":"f867002d74c23c7cd0e6fa73f656963c83d02a6e62e54990b427ab0aab24d2ac"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: Implement custom handling for default commands and solve this somehow globally. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/GameEditViewModel.cs"},"region":{"startLine":544}}}],"partialFingerprints":{"codehealthFindingId/v1":"2b89f584d21a32ab91651de5962252b4fe889bee152d8ab8bde5d6534ed5b00f"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: fix the desync. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/FullscreenTilePanel.cs"},"region":{"startLine":219}}}],"partialFingerprints":{"codehealthFindingId/v1":"36b88b76df5aede4f13bc72464464a15e4b2f1fe4835e288b0c44625d11325f4"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO handle properly in future via TODO from SelectedGame property"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/Views/GameDetails.cs"},"region":{"startLine":81}}}],"partialFingerprints":{"codehealthFindingId/v1":"ec6d110791832d2188f31527db0a3fd0b11f5daffe4b57939cca35de35b1182b"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO completely rework and decouple selected game from main view and game details \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/ViewModels/FullscreenAppViewModel.cs"},"region":{"startLine":162}}}],"partialFingerprints":{"codehealthFindingId/v1":"c62f697915d87ff76d95bd909f39456319a2a22ce281f73262b454247a043c6d"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS0067 \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/API/DatabaseAPI.cs"},"region":{"startLine":20}}}],"partialFingerprints":{"codehealthFindingId/v1":"c081e702fda8b1b4ff508f257daf53656b951e31cad729457372e8c2e60d6970"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS0067 \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/InMemoryGameDatabase.cs"},"region":{"startLine":68}}}],"partialFingerprints":{"codehealthFindingId/v1":"3b0a752df9c8df25b600f274d84045a7961c03cec37d6f4c0f784e86305c890a"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: remove after switch to .NET 5 \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/App/PlayniteApplication.cs"},"region":{"startLine":102}}}],"partialFingerprints":{"codehealthFindingId/v1":"e912ebc9bd21e30a40b270b15f023e567d3b864901e441a80a4b2b496c46da29"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: Modify scaling to scale by both axies. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/BitmapExtensions.cs"},"region":{"startLine":247}}}],"partialFingerprints":{"codehealthFindingId/v1":"3596a19cf55ef8880fbd49c189d249037f80aaca8b621bdf4975ab02e6f3415a"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO Add support for lists \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/Extensions/CloneObject.cs"},"region":{"startLine":175}}}],"partialFingerprints":{"codehealthFindingId/v1":"ab80e780949812e02f7475ef007fe3c2e1a76b9cbe238bc315c48907c8eeb854"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO Rework with proper symlinks handling with FileSystemInfo.ResolveLinkTarget \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Common/FileSystem.cs"},"region":{"startLine":369}}}],"partialFingerprints":{"codehealthFindingId/v1":"e5f37148b0581fe16d839bf046eaf455de1c8fc39b8ccbb961d0fcc05979dd4a"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Controllers/GenericGameController.cs"},"region":{"startLine":24}}}],"partialFingerprints":{"codehealthFindingId/v1":"3d770ae211ce63c7e70e3a6fc051d5a8e1f7f52ba5b059871d985018f33f3044"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: Rewrite this mess. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/DatabaseExplorer.cs"},"region":{"startLine":73}}}],"partialFingerprints":{"codehealthFindingId/v1":"aa0e5ab181a71b23e9517dba53e0eca4bbbd28f51ccb3e0ddb320b4fc6ee5e54"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: Remove this, we should only allow path to be set during instantiation. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Database/GameDatabase.cs"},"region":{"startLine":466}}}],"partialFingerprints":{"codehealthFindingId/v1":"01e5e7697ecc38ff4426b5257274e6d2d22df609cc777ec353f3422277838de0"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: handle properly \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/DateTimes.cs"},"region":{"startLine":100}}}],"partialFingerprints":{"codehealthFindingId/v1":"94944a2d9b3c4996b85766f97617c05629558cdcbc8975929ba4bde6f2298ae1"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO rework this whole mess into something better and more maintainable :| \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Extensions/GameExtensions.cs"},"region":{"startLine":184}}}],"partialFingerprints":{"codehealthFindingId/v1":"511edb3dc6e2059f69a18d33b47428883b42356164287364de166ead965acd57"}},{"ruleId":"D17","level":"warning","message":{"text":"BareSuppressMessage repeated 10 times in one file: The identical BareSuppressMessage (\u0060SuppressMessage\u0060) appears 10 times in one file \u2014 one decision applied repeatedly (e.g. the same rule silenced on every overload of a fluent API), not 10 independent debts. Decide it once \u2014 at the type or project level, or by fixing the underlying pattern \u2014 rather than occurrence-by-occurrence. (Every occurrence still counts toward the score and metrics.)"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Native/Windef.cs"},"region":{"startLine":110}}}],"partialFingerprints":{"codehealthFindingId/v1":"015d5b0018526566f4899e8f39379d961398577a41dac773441a90b66767e313"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: Unload assembly once Playnite switches to .NET Core \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":492}}}],"partialFingerprints":{"codehealthFindingId/v1":"14e852580e642009c895a464b2d170ca3619b6c13ca20a32151db34681018fb3"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: /* TODO: This #ifdef is only here because the equivalent\n\t\t\t * .NET 2.0 constructor appears to be less efficient?\n\t\t\t * Here\u0027s the pretty version, maybe steal this instead:\n\t\t\t *\n\t\t\tstring result = new string(\n\t\t\t\t(sbyte*) s, // Also, why sbyte???\n\t\t\t\t0,\n\t\t\t\t(int) (ptr - (byte*) s),\n\t\t\t\tSystem.Text.Encoding.UTF8\n\t\t\t);\n\t\t\t * See the CoreCLR source for more info.\n\t\t\t * -flibit\n\t\t\t */ \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":142}}}],"partialFingerprints":{"codehealthFindingId/v1":"de8cc2f204ddefa66e9b45b8e288a26e5a7371a7e6760427ce81d601df0d78b0"}},{"ruleId":"D17","level":"warning","message":{"text":"FixmeComment: // FIXME: I\u0027d rather this somehow be private... \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":7018}}}],"partialFingerprints":{"codehealthFindingId/v1":"51e83732ca99c0b763fd79f3520f1f3d24c05655780f6b08c03636b1c43181a7"}},{"ruleId":"D17","level":"warning","message":{"text":"FixmeComment: // FIXME: I\u0027d rather this somehow be private... \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":7026}}}],"partialFingerprints":{"codehealthFindingId/v1":"6db62bbdfb1faa13b01fac9de70ede74eb67bef71469168e105ab5340df05152"}},{"ruleId":"D17","level":"warning","message":{"text":"FixmeComment: // FIXME: I wish these weren\u0027t public... \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":8666}}}],"partialFingerprints":{"codehealthFindingId/v1":"b679f2651cb96512814e90cffda316290ed0ae1f9e091c0cb5ae02450687f4fa"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable repeated 12 times in one file: The identical BarePragmaDisable (\u0060#pragma warning disable 0169\u0060) appears 12 times in one file \u2014 one decision applied repeatedly (e.g. the same rule silenced on every overload of a fluent API), not 12 independent debts. Decide it once \u2014 at the type or project level, or by fixing the underlying pattern \u2014 rather than occurrence-by-occurrence. (Every occurrence still counts toward the score and metrics.)"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SDL2.cs"},"region":{"startLine":4998}}}],"partialFingerprints":{"codehealthFindingId/v1":"e002878e221df2206ed6bdb163aaed7d2ee60fbf504952357274895e35d9dd6e"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: refactor this and merge it with NamedObject and SelectableItem \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SelectableItem.cs"},"region":{"startLine":81}}}],"partialFingerprints":{"codehealthFindingId/v1":"a25448c7216ec7a710e19a60844cef7715bbe743b74346fbb530fa3978f15124"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: refactor this and merge it with NamedObject and SelectableNamedObject \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/SelectableItem.cs"},"region":{"startLine":101}}}],"partialFingerprints":{"codehealthFindingId/v1":"0265e17f0822704771923a5a62f5bca95fe2ef3e3b47559d84b8d02377e44326"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO replace this in future by exposing GamesCollectionViewEntry to SDK and let plugins create them directly. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":226}}}],"partialFingerprints":{"codehealthFindingId/v1":"20892d49ad2603510698027a7f8b9817196219e3cdc72963aa91bac4c1f0c9b7"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO definitely could use some improvements for better fuzzy results. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/ViewModels/SearchViewModel.cs"},"region":{"startLine":704}}}],"partialFingerprints":{"codehealthFindingId/v1":"cb69260db3bcad5de5e445fbf8050c7a15e4e4e3e01eba6b51f4eea2732cece9"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO: this needs complete rework when per display DPI support is enabled in P11. \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Windows/WindowPositionHandler.cs"},"region":{"startLine":145}}}],"partialFingerprints":{"codehealthFindingId/v1":"2e8e7358710ab4d1f64ad222e5f7cf6f36ff58ef131a4cd61394a65a5ba2865d"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/Events/ApplicationEvents.cs"},"region":{"startLine":10}}}],"partialFingerprints":{"codehealthFindingId/v1":"64c9136c64d50573d7bcd6e9672845f8e5c83b814ab362e239f0a675665baa08"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/IDialogsFactory.cs"},"region":{"startLine":10}}}],"partialFingerprints":{"codehealthFindingId/v1":"d90dc98f2a4728b8f32a723a9fb3cc5a77073c2d3f57f3171bf792d5c91e492f"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/IWebView.cs"},"region":{"startLine":12}}}],"partialFingerprints":{"codehealthFindingId/v1":"9443babea1a0d3db74ac0685622e62c9e75faa5eae359a1c64ceecf5d5caca3f"}},{"ruleId":"D17","level":"warning","message":{"text":"BarePragmaDisable: #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member \u2014 the disable has no matching restore, so it does not end with the construct that needed it: it runs to the end of the file and silences the rule for everything written below, including code added years later. Close it with the matching restore directive immediately after the construct it covers, or fix the cause and drop the directive entirely."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/WebViewModels.cs"},"region":{"startLine":7}}}],"partialFingerprints":{"codehealthFindingId/v1":"24243a5445a2df6897a74835a3c8f8b7b67932dbfb35e93cd5419513c6a16d11"}},{"ruleId":"D17","level":"note","message":{"text":"ObsoleteWithoutCallers: [Obsolete] ForcePlayTimeSync"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/IPlayniteSettingsAPI.cs"},"region":{"startLine":174}}}],"partialFingerprints":{"codehealthFindingId/v1":"06cac11d8dc36a85235fee84be3d7f274f1a19aaec67ca094be8a29cb615a4d3"}},{"ruleId":"D17","level":"note","message":{"text":"ObsoleteWithoutCallers: [Obsolete] CacheEnabled"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/PlayniteSDK/IWebView.cs"},"region":{"startLine":62}}}],"partialFingerprints":{"codehealthFindingId/v1":"434193310fb5d5d4e661b27224c7cd0569ef9dbd2f50a238ba30174df33a9a94"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO add file test \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.DesktopApp.Tests/ViewModels/DatabaseFieldsManagerViewModelTests.cs"},"region":{"startLine":82}}}],"partialFingerprints":{"codehealthFindingId/v1":"7efc9ca92807352875c7a64be199e0d557c6a98b4a09bf3a196f5dc4402277a2"}},{"ruleId":"D17","level":"warning","message":{"text":"TodoComment: // TODO \u2014 source code is not a task system: move the work to your tracker and leave a reference instead (e.g. \u0060// REF: #123\u0060), so the task is planned where tasks live and the ticket links back to the code."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.Tests/App/UpdateTests.cs"},"region":{"startLine":29}}}],"partialFingerprints":{"codehealthFindingId/v1":"cfda58695394e2bd79d2b18f4fa8a6e23465b4ce3aad459f96314c4725666113"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 5 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.Tests/App/UpdateTests.cs"},"region":{"startLine":35}}}],"partialFingerprints":{"codehealthFindingId/v1":"2e517ea1614f01bc124bdd8cfbefcf785e021f221a7ffec0291f1fd30f979738"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 7 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/Playnite.Tests/App/UpdateTests.cs"},"region":{"startLine":41}}}],"partialFingerprints":{"codehealthFindingId/v1":"c2de3c13ff16e577f14d94669f8343773946b7165f7082acdc7a51bad84a96f8"}},{"ruleId":"D17","level":"warning","message":{"text":"CommentedOutCode: 7 consecutive commented-code lines"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Tests/TestPlugin/TestPlugin.cs"},"region":{"startLine":368}}}],"partialFingerprints":{"codehealthFindingId/v1":"d8544366f60564e577ca652bb43882c89ca3ed5f59319419d01c354df88944e6"}},{"ruleId":"D18","level":"warning","message":{"text":"Monorepo: only 1 of 6 solutions was scored: This repository contains 6 .NET solutions, but a scan analyzes ONE. Every score, lens, and finding here reflects only \u0060source/Playnite.sln\u0060 \u2014 the other 5 (\u0060source/Tools/Playnite.Toolbox/Templates/Extensions/CustomLibraryPlugin/CustomLibraryPlugin.sln\u0060, \u0060source/Tools/Playnite.Toolbox/Templates/Extensions/CustomMetadataPlugin/CustomMetadataPlugin.sln\u0060, \u0060source/Tools/Playnite.Toolbox/Templates/Extensions/GenericPlugin/GenericPlugin.sln\u0060, \u0060source/Tools/Playnite.Toolbox/Templates/Themes/Desktop/Theme.sln\u0060, \u0060source/Tools/Playnite.Toolbox/Templates/Themes/Fullscreen/Theme.sln\u0060) were not analyzed and are not represented in the headline. To cover them, scan each solution as its own target and group them in a Solution or Product for a portfolio roll-up. If a secondary solution is an archived or vendored tree, declare it \u2014 \u0060.gitattributes\u0060 (\u0060path/** linguist-vendored\u0060) or \u0060.editorconfig\u0060 (\u0060[path/**] generated_code = true\u0060) \u2014 to exclude it from discovery the same way generated code is."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"e9820d63ad953a490cc55d49a4e9b151f9620059ccf07407771ad51beb70154c"}},{"ruleId":"D18","level":"note","message":{"text":"Thin analysable surface across projects: 1 project(s) carry only a thin slice of real code (e.g. \u0060Playnite.FullscreenApp.Tests\u0060 with 44 significant line(s)). The mean analysable-surface weight is 99 %, lowering Solution Shape by about 0.08 point(s). Consolidate thin projects or grow them into substantial, well-scoped assemblies."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"dd0b92fd965c2065080f16843920964ee00f7696ea03d87cdf61aed4cd2c746a"}},{"ruleId":"D20","level":"note","message":{"text":"No ADRs found: No ADRs found at common paths; consider documenting architectural decisions in Docs/ADL/ or similar."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"d2bea044ff79d7d275f5a91a6e2f548586178eaf480274c33960ad020c854631"}},{"ruleId":"D21","level":"note","message":{"text":"Inconsistent pluralization for collection-like properties. \u0027Genres\u0027 is correctly pluralized, while \u0027Serie\u0027 is singular, likely referring to a collection of series.: Rename \u0027Serie\u0027 to \u0027Series\u0027 to match the pluralization convention seen in \u0027Genres\u0027 and other collection properties. (symbols: Playnite.GamesCollectionViewEntry.Serie, Playnite.SDK.Models.Game.Genres)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"0d0dc7a47ebc7c685b94268916ac3ef67c75b1ce8fffd09b877bbb2e62f977c8"}},{"ruleId":"D21","level":"note","message":{"text":"Inconsistent spelling of \u0027Behaviors\u0027 in the namespace/assembly name. \u0027FocusBahaviors\u0027 appears to be a typo (missing \u0027h\u0027 in Behaviors) or a misspelling of the standard \u0027Behaviors\u0027 used elsewhere in the codebase.: Rename \u0027FocusBahaviors\u0027 to \u0027FocusBehaviors\u0027 to match the correct spelling \u0027Behaviors\u0027 used in \u0027ScrollViewerBehaviours\u0027 and other parts of the codebase. (symbols: Playnite.Behaviors.FocusBahaviors.SetOnVisibilityFocus, Playnite.Behaviors.ScrollViewerBehaviours.SetSensitivity, Playnite.Behaviors.ScrollViewerBehaviours.GetSpeed)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"1b381eb7b521fe9464c92904fe57f7e5ba6495355c6ba36abe7755a8591eaf18"}},{"ruleId":"D21","level":"note","message":{"text":"Typo in property name: \u0027Keywrods\u0027 is misspelled.: Rename \u0027CustomSearchKeywrods\u0027 to \u0027CustomSearchKeywords\u0027. (symbols: Playnite.PlayniteSettings.CustomSearchKeywrods, Playnite.PlayniteSettings.SaveGlobalSearchFilterSettings)"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"88b27237ad519bd6b294d36673d956b1e4e0e9d6bdf12e6454abcf47b07dd2cd"}},{"ruleId":"D23","level":"note","message":{"text":"Bounded contexts not declared: At 118455 LoC spread over 15 projects the codebase is large and multi-module, so explicit bounded contexts are needed. Name this codebase\u0027s bounded contexts (\u22652 module groups, e.g. per subsystem) so cross-boundary type coupling can be assessed. Declare them in \u0060.codehealth/config.yaml\u0060 at the repository root (create it if absent), mapping each context name to the module-path or namespace prefixes that belong to it \u2014 e.g. \u0060architecture:\u0060 \u2192 \u0060contexts:\u0060 \u2192 \u0060Billing: [\u0022src/billing\u0022, \u0022Acme.Billing\u0022]\u0060, \u0060Catalog: [\u0022src/catalog\u0022, \u0022Acme.Catalog\u0022]\u0060."},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"1c7e276c9c682731f01819ed5378b90ca320cde1b583c90920172911598362b3"}},{"ruleId":"D24","level":"note","message":{"text":"redundant comment: \u0022Remove deleted from database\u0022 \u2014 weak keep - notes a non-obvious side-effect; could link to the delete code"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.DesktopApp/ViewModels/ToolsConfigViewModel.cs"},"region":{"startLine":156}}}],"partialFingerprints":{"codehealthFindingId/v1":"16ed776e18c748776ee3af48237710d64ae976ca2a6ee0da020adccc37b387e0"}},{"ruleId":"D26","level":"note","message":{"text":"Split Playnite: A large catch-all name that is huge (68k LoC) and sprawls over 39 unrelated namespaces. Suggested: by namespace: Playnite.Content, Playnite.Media, Playnite.Scheduling"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"b85611fd78a8ddb024f5104ab7f5f819e2d37c2920260af5cf255fc5cd74633a"}},{"ruleId":"D26","level":"note","message":{"text":"Split Playnite.DesktopApp: Catch-all desktop app that is large and spans many unrelated namespaces. Suggested: by namespace: Playnite.Views, Playnite.Interactivity, Playnite.Licensing"},"locations":[],"partialFingerprints":{"codehealthFindingId/v1":"b1a8d543383931f150f38f2c807da71bc2acb739c592dda3938fbc9f077b1053"}},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"1edc4f9288c4d81aab38fc41bb0bf2693c1a0855f87ca22a7871e7496e743b00"},"taxa":[{"id":"CWE-1333","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"0ef91953679e956dae64fdd37c4560c726919ec53884f1ff98559b320e4ca37b"},"taxa":[{"id":"CWE-1333","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"b543db4712076c57ca599a16293386d7d21fe81d10825065a0b74691db46319b"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"ea7212600964332ff285c78da969c0b65617803b429726af01f28e2ebeb669fc"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"344bb521056b3858c35dcf0bebd5bce9c26996f7ba19047170c9b557afb566f7"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"35abe0ff4bcd9181af5081b47f45d3e85dd4004c02609825d648c531c35546f4"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"ffb041b23c8c2f6811e33a293f5aad7ec792fb670572d2504de1831bd60eeda6"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"12ba4edf9cc9c80d3d31e7bfa1f3dcadfb1c3454c7ffded0174a2f93ebe1f6c2"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"1e409816398e2993bb119cdf282d912563fae7b8dad603d3bb111af2e3a1c31d"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"6cd8f62c1f072bfb08e4e8a7a896937c568a4980420cdd6e5d32102165504473"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"f456e479ed7234444c133bfafca4b5e6a63e857f1bbb166fae0c2d096368a4be"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D29","level":"warning","message":{"text":"A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."},"partialFingerprints":{"codehealthFindingId/v1":"4232527876a77fc80115004fff3506cc62305ffe5d2fbe2fbe67a8d33cd920f8"},"taxa":[{"id":"CWE-22","toolComponent":{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d"}}]},{"ruleId":"D35","level":"warning","message":{"text":"Change coupling: DesignPlayniteAPI.cs \u2194 PlayniteAPI.cs: \u0060source/Playnite/API/DesignData/DesignPlayniteAPI.cs\u0060 and \u0060source/Playnite/API/PlayniteAPI.cs\u0060 change together 77% of the time (10 of the 13 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well). They sit in different directories, but in this ecosystem the namespace is declared in the FILE, not by the folder \u2014 so the two may well share one namespace and reference each other with no import for this pass to see. Read the pair before acting: if one derives from or overrides the other, the dependency is explicit in the type declaration and the co-change is definitional; if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE and the thing to add is a comment saying so; if they simply belong together, co-locate them; if none of these holds, the coupling is hidden and worth breaking."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/API/DesignData/DesignPlayniteAPI.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"3530be50175ac9bc7a3c2569e1e0448e51957fd5f622abc2ecdfe5abf02af1ac"}},{"ruleId":"D35","level":"warning","message":{"text":"Change coupling: ExtensionFactory.cs \u2194 PowerShellScript.cs: \u0060source/Playnite/Plugins/ExtensionFactory.cs\u0060 and \u0060source/Playnite/Scripting/PowerShell/PowerShellScript.cs\u0060 change together 53% of the time (10 of the 19 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well). They sit in different directories, but in this ecosystem the namespace is declared in the FILE, not by the folder \u2014 so the two may well share one namespace and reference each other with no import for this pass to see. Read the pair before acting: if one derives from or overrides the other, the dependency is explicit in the type declaration and the co-change is definitional; if one registers itself into the other through a hook or an initialiser, the missing dependency is DELIBERATE and the thing to add is a comment saying so; if they simply belong together, co-locate them; if none of these holds, the coupling is hidden and worth breaking."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite/Plugins/ExtensionFactory.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"8843d2ebf87ab86b4b965f4e9f8f404ba6394d2f0d2cb517fab68c36618da5c7"}},{"ruleId":"D35","level":"warning","message":{"text":"Change coupling: GameDetails.cs \u2194 Main.cs: \u0060source/Playnite.FullscreenApp/Controls/Views/GameDetails.cs\u0060 and \u0060source/Playnite.FullscreenApp/Controls/Views/Main.cs\u0060 change together 50% of the time (10 of the 20 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well). They sit in the same directory, and in this ecosystem sibling files there normally share one namespace/package \u2014 so a direct reference between them needs no import and this pass cannot see whether one exists. Read the pair before acting: if one file only DECLARES what the other consumes (a constants/types file beside its user), the co-change is definitional and the question is whether the split earns its keep; if they duplicate structure, extract the common part into a shared function or type they both call; if neither holds, the coupling is hidden and worth breaking."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/Views/GameDetails.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"8778ad35f85c74dac352645b6ba6f2cbde7431340b93b94b30610d70bc4ce4cd"}},{"ruleId":"D35","level":"warning","message":{"text":"Change coupling: Filters.cs \u2194 FiltersAdditional.cs: \u0060source/Playnite.FullscreenApp/Controls/Views/Filters.cs\u0060 and \u0060source/Playnite.FullscreenApp/Controls/Views/FiltersAdditional.cs\u0060 change together 50% of the time (7 of the 14 commits that touched whichever of the two files changed less often, counting a file under its earlier names as well). They sit in the same directory, and in this ecosystem sibling files there normally share one namespace/package \u2014 so a direct reference between them needs no import and this pass cannot see whether one exists. Read the pair before acting: if one file only DECLARES what the other consumes (a constants/types file beside its user), the co-change is definitional and the question is whether the split earns its keep; if they duplicate structure, extract the common part into a shared function or type they both call; if neither holds, the coupling is hidden and worth breaking."},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"source/Playnite.FullscreenApp/Controls/Views/Filters.cs"},"region":{"startLine":1}}}],"partialFingerprints":{"codehealthFindingId/v1":"80957e85fa236a0ab3f3fef540321b601763153a272c033138386947535c1e99"}}],"taxonomies":[{"name":"CWE","guid":"c3a2b1d0-7f3e-4b2a-9c1d-5e6f7a8b9c0d","organization":"MITRE","informationUri":"https://cwe.mitre.org/","isComprehensive":false,"shortDescription":{"text":"The MITRE Common Weakness Enumeration (CWE)."},"taxa":[{"id":"CWE-1333","guid":"11a336ce-63de-c45c-845e-29ca1e8df13d","name":"CWE-1333","shortDescription":{"text":"CWE-1333"},"helpUri":"https://cwe.mitre.org/data/definitions/1333.html"},{"id":"CWE-22","guid":"b68d9ca7-bdde-d057-a6cc-9f8b1e739552","name":"CWE-22","shortDescription":{"text":"CWE-22"},"helpUri":"https://cwe.mitre.org/data/definitions/22.html"},{"id":"CWE-259","guid":"ae9ad959-fbb6-9d5e-892d-3dca66da0b69","name":"Use of Hard-coded Password","shortDescription":{"text":"Use of Hard-coded Password"},"helpUri":"https://cwe.mitre.org/data/definitions/259.html"},{"id":"CWE-77","guid":"332c8ade-6612-9f56-a06b-d8d90b1a8750","name":"Command Injection","shortDescription":{"text":"Command Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/77.html"},{"id":"CWE-78","guid":"2e31ceaf-c7ae-2e5e-9661-cfb1362789cf","name":"OS Command Injection","shortDescription":{"text":"OS Command Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/78.html"},{"id":"CWE-79","guid":"fd45580b-e8c4-fc5e-8c2f-aa8fab0b4dbf","name":"Cross-site Scripting (XSS)","shortDescription":{"text":"Cross-site Scripting (XSS)"},"helpUri":"https://cwe.mitre.org/data/definitions/79.html"},{"id":"CWE-798","guid":"5e8f057d-fee3-995a-a0cb-9fc5b0d174d1","name":"Use of Hard-coded Credentials","shortDescription":{"text":"Use of Hard-coded Credentials"},"helpUri":"https://cwe.mitre.org/data/definitions/798.html"},{"id":"CWE-89","guid":"6d08fdad-37eb-c150-bbf0-d7d946863407","name":"SQL Injection","shortDescription":{"text":"SQL Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/89.html"},{"id":"CWE-94","guid":"75e7f50c-6c2f-dd52-bf40-bf6c52b861fd","name":"Code Injection","shortDescription":{"text":"Code Injection"},"helpUri":"https://cwe.mitre.org/data/definitions/94.html"}]}],"properties":{"codehealthPublication":{"public":true,"notice":"This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings \u2014 which rule fired, in which file, on which line, and how to fix it \u2014 are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.","securityFindingsRedacted":12,"secretScannerRunsExcluded":0}},"redactionTokens":["A security finding was recorded here. Its details are withheld on the public artifact \u2014 ask the repository owner for the full report."]}]}