From 138deb795c26f1744dd0688d8e9c57157c0261a6 Mon Sep 17 00:00:00 2001 From: Mary Georgiou <89914005+mary-georgiou-sonarsource@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:37:04 +0200 Subject: [PATCH] Fix S2259 FP: SE engine doesn't take into account element existence collection methods (#9505) --- .../Ember-MM/S2259-Ember Media Manager.json | 36 --- .../its/expected/Ember-MM/S2259-EmberAPI.json | 6 - .../Ember-MM/S2259-generic.EmberCore.NMT.json | 126 ---------- .../Ember-MM/S2259-scraper.EmberCore.XML.json | 96 -------- .../Ember-MM/S2259-scraper.EmberCore.json | 216 ------------------ ...589-Akka.Cluster.Tools-netstandard2.0.json | 6 - .../Invocation.Enumerable.cs | 44 +++- .../RoslynSymbolicExecutionTest.Invocation.cs | 104 ++++++++- .../Roslyn/NullPointerDereference.cs | 2 +- 9 files changed, 133 insertions(+), 503 deletions(-) diff --git a/analyzers/its/expected/Ember-MM/S2259-Ember Media Manager.json b/analyzers/its/expected/Ember-MM/S2259-Ember Media Manager.json index cb6b1dc26da..13f21852cff 100644 --- a/analyzers/its/expected/Ember-MM/S2259-Ember Media Manager.json +++ b/analyzers/its/expected/Ember-MM/S2259-Ember Media Manager.json @@ -6,47 +6,11 @@ "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgErrorViewer.vb#L64", "Location": "Line 64 Position 65-72" }, - { - "Id": "S2259", - "Message": "\u0027Me.tLangList.FirstOrDefault(Function(l) l.ShortLang = Master.eSettings.TVDBLanguage)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgSettings.vb#L2499", - "Location": "Line 2499 Position 40-124" - }, { "Id": "S2259", "Message": "\u0027Me.SettingsPanels.FirstOrDefault(Function(p) p.Name = tvSettings.SelectedNode.Name)\u0027 is Nothing on at least one execution path.", "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgSettings.vb#L4315", "Location": "Line 4315 Position 24-107" - }, - { - "Id": "S2259", - "Message": "\u0027Me.tLangList.FirstOrDefault(Function(l) l.ShortLang = Master.eSettings.TVDBLanguage)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgSettings.vb#L836", - "Location": "Line 836 Position 36-120" - }, - { - "Id": "S2259", - "Message": "\u0027MyTVShowRegExProfiles.Profiles.FirstOrDefault(Function(y) y.Name = lstProfiles.SelectedItems(0).Text)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgTVRegExProfiles.vb#L13", - "Location": "Line 13 Position 36-137" - }, - { - "Id": "S2259", - "Message": "\u0027Me.tLangList.FirstOrDefault(Function(l) l.ShortLang = Master.eSettings.TVDBLanguage)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgWizard.vb#L175", - "Location": "Line 175 Position 27-111" - }, - { - "Id": "S2259", - "Message": "\u0027tLangList.FirstOrDefault(Function(l) l.LongLang = Me.cbTVLanguage.Text)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgWizard.vb#L371", - "Location": "Line 371 Position 26-97" - }, - { - "Id": "S2259", - "Message": "\u0027Me.tLangList.FirstOrDefault(Function(l) l.ShortLang = Master.eSettings.TVDBLanguage)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Ember%20Media%20Manager/dlgWizard.vb#L444", - "Location": "Line 444 Position 27-111" } ] } \ No newline at end of file diff --git a/analyzers/its/expected/Ember-MM/S2259-EmberAPI.json b/analyzers/its/expected/Ember-MM/S2259-EmberAPI.json index c6191e8f63d..42a53bead17 100644 --- a/analyzers/its/expected/Ember-MM/S2259-EmberAPI.json +++ b/analyzers/its/expected/Ember-MM/S2259-EmberAPI.json @@ -12,12 +12,6 @@ "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/EmberAPI/clsAdvancedSettings.vb#L215", "Location": "Line 215 Position 25-120" }, - { - "Id": "S2259", - "Message": "\u0027cs\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/EmberAPI/clsAdvancedSettings.vb#L231", - "Location": "Line 231 Position 21-23" - }, { "Id": "S2259", "Message": "\u0027_AdvancedSettings.FirstOrDefault(Function(f) f.Name = key AndAlso f.Section = Assembly)\u0027 is Nothing on at least one execution path.", diff --git a/analyzers/its/expected/Ember-MM/S2259-generic.EmberCore.NMT.json b/analyzers/its/expected/Ember-MM/S2259-generic.EmberCore.NMT.json index 9829dbeca5c..5201e8ad4e0 100644 --- a/analyzers/its/expected/Ember-MM/S2259-generic.EmberCore.NMT.json +++ b/analyzers/its/expected/Ember-MM/S2259-generic.EmberCore.NMT.json @@ -1,113 +1,5 @@ { "Issues": [ - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movieindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1498", - "Location": "Line 1498 Position 168-253" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movieindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1498", - "Location": "Line 1498 Position 71-156" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1561", - "Location": "Line 1561 Position 165-247" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1561", - "Location": "Line 1561 Position 71-153" - }, - { - "Id": "S2259", - "Message": "\u0027r.values.FirstOrDefault(Function(y) y.value = v)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L166", - "Location": "Line 166 Position 97-145" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Params.FirstOrDefault(Function(y) y.name = dgvSettings.Rows(e.RowIndex).Cells(0).Value.ToString)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1695", - "Location": "Line 1695 Position 29-130" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Properties.FirstOrDefault(Function(y) y.name = dgvProperties.Rows(e.RowIndex).Tag.ToString)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L1706", - "Location": "Line 1706 Position 29-125" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movieindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L298", - "Location": "Line 298 Position 61-146" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movie\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L299", - "Location": "Line 299 Position 68-148" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movieindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L339", - "Location": "Line 339 Position 64-149" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022movie\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L341", - "Location": "Line 341 Position 85-165" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L380", - "Location": "Line 380 Position 61-143" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvshow\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L381", - "Location": "Line 381 Position 72-153" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvseason\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L382", - "Location": "Line 382 Position 74-157" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvepisode\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L383", - "Location": "Line 383 Position 70-154" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvindex\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L413", - "Location": "Line 413 Position 64-146" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvshow\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L427", - "Location": "Line 427 Position 79-160" - }, - { - "Id": "S2259", - "Message": "\u0027conf.Files.FirstOrDefault(Function(y) y.Process = True AndAlso y.Type = \u0022tvseason\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L443", - "Location": "Line 443 Position 85-168" - }, { "Id": "S2259", "Message": "\u0027mediaPath\u0027 is Nothing on at least one execution path.", @@ -119,24 +11,6 @@ "Message": "\u0027fiAV\u0027 is Nothing on at least one execution path.", "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L620", "Location": "Line 620 Position 24-28" - }, - { - "Id": "S2259", - "Message": "\u0027c.values.FirstOrDefault(Function(y) y.label = saved)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L960", - "Location": "Line 960 Position 42-94" - }, - { - "Id": "S2259", - "Message": "\u0027p\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L998", - "Location": "Line 998 Position 13-14" - }, - { - "Id": "S2259", - "Message": "\u0027p.values.FirstOrDefault(Function(y) y.label = s)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/generic.EmberCore.NMT/dlgNMTMovies.vb#L998", - "Location": "Line 998 Position 23-71" } ] } \ No newline at end of file diff --git a/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.XML.json b/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.XML.json index 29d5fc329e5..b7eb75062c6 100644 --- a/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.XML.json +++ b/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.XML.json @@ -1,101 +1,5 @@ { "Issues": [ - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L51", - "Location": "Line 51 Position 36-164" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.PostScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L53", - "Location": "Line 53 Position 17-123" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L54", - "Location": "Line 54 Position 17-145" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L63", - "Location": "Line 63 Position 36-164" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L72", - "Location": "Line 72 Position 36-164" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.PostScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L74", - "Location": "Line 74 Position 17-123" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLMediaSettingsHolder.vb#L75", - "Location": "Line 75 Position 17-145" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L108", - "Location": "Line 108 Position 32-160" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L110", - "Location": "Line 110 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L111", - "Location": "Line 111 Position 13-141" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L117", - "Location": "Line 117 Position 32-160" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L123", - "Location": "Line 123 Position 32-160" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L125", - "Location": "Line 125 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberXMLScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/frmXMLSettingsHolder.vb#L126", - "Location": "Line 126 Position 13-141" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.OrderBy(Function(y) y.ScraperOrder).FirstOrDefault(Function(e) e.ProcessorModule.IsScraper AndAlso e.ProcessorModule.ScraperEnabled)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/scraperMovieXMLModule.vb#L234", - "Location": "Line 234 Position 21-201" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.OrderBy(Function(y) y.ScraperOrder).FirstOrDefault(Function(e) e.ProcessorModule.IsScraper AndAlso e.ProcessorModule.ScraperEnabled)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore.XML/scraperMovieXMLModule.vb#L291", - "Location": "Line 291 Position 21-201" - }, { "Id": "S2259", "Message": "\u0027obj\u0027 is Nothing on at least one execution path.", diff --git a/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.json b/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.json index 0e31814f54d..6230d62c122 100644 --- a/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.json +++ b/analyzers/its/expected/Ember-MM/S2259-scraper.EmberCore.json @@ -1,226 +1,10 @@ { "Issues": [ - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L188", - "Location": "Line 188 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L37", - "Location": "Line 37 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L39", - "Location": "Line 39 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L40", - "Location": "Line 40 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L47", - "Location": "Line 47 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L49", - "Location": "Line 49 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmInfoSettingsHolder.vb#L50", - "Location": "Line 50 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L120", - "Location": "Line 120 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L37", - "Location": "Line 37 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.PostScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L39", - "Location": "Line 39 Position 13-119" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L40", - "Location": "Line 40 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L47", - "Location": "Line 47 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.PostScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L49", - "Location": "Line 49 Position 13-119" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmMediaSettingsHolder.vb#L50", - "Location": "Line 50 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L37", - "Location": "Line 37 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L39", - "Location": "Line 39 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L40", - "Location": "Line 40 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L47", - "Location": "Line 47 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L49", - "Location": "Line 49 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L50", - "Location": "Line 50 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVInfoSettingsHolder.vb#L67", - "Location": "Line 67 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L37", - "Location": "Line 37 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order \u002B 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L39", - "Location": "Line 39 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L40", - "Location": "Line 40 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L47", - "Location": "Line 47 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.ScraperOrder = order - 1)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L49", - "Location": "Line 49 Position 13-115" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L50", - "Location": "Line 50 Position 13-144" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.FirstOrDefault(Function(p) p.AssemblyName = EmberNativeScraperModule._AssemblyName)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/frmTVMediaSettingsHolder.vb#L67", - "Location": "Line 67 Position 32-163" - }, - { - "Id": "S2259", - "Message": "\u0027ModulesManager.Instance.externalScrapersModules.OrderBy(Function(y) y.ScraperOrder).FirstOrDefault(Function(e) e.ProcessorModule.IsScraper AndAlso e.ProcessorModule.ScraperEnabled)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/scraperMovieNativeModule.vb#L560", - "Location": "Line 560 Position 21-201" - }, { "Id": "S2259", "Message": "\u0027sResults\u0027 is Nothing on at least one execution path.", "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVDBSearchResults.vb#L336", "Location": "Line 336 Position 24-32" - }, - { - "Id": "S2259", - "Message": "\u0027sResults.OrderBy(Function(s) s.Lev).FirstOrDefault(Function(s) s.Language.ShortLang = \u0022en\u0022)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVDBSearchResults.vb#L358", - "Location": "Line 358 Position 54-145" - }, - { - "Id": "S2259", - "Message": "\u0027DefaultImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1018", - "Location": "Line 1018 Position 39-120" - }, - { - "Id": "S2259", - "Message": "\u0027Scraper.TVDBImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1019", - "Location": "Line 1019 Position 17-103" - }, - { - "Id": "S2259", - "Message": "\u0027DefaultImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1022", - "Location": "Line 1022 Position 51-132" - }, - { - "Id": "S2259", - "Message": "\u0027Scraper.TVDBImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1023", - "Location": "Line 1023 Position 51-137" - }, - { - "Id": "S2259", - "Message": "\u0027Scraper.TVDBImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1058", - "Location": "Line 1058 Position 17-103" - }, - { - "Id": "S2259", - "Message": "\u0027Scraper.TVDBImages.SeasonImageList.FirstOrDefault(Function(s) s.Season = Me.SelSeason)\u0027 is Nothing on at least one execution path.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/Ember-MM/Addons/scraper.EmberCore/TVScraper/dlgTVImageSelect.vb#L1060", - "Location": "Line 1060 Position 50-136" } ] } \ No newline at end of file diff --git a/analyzers/its/expected/akka.net/S2589-Akka.Cluster.Tools-netstandard2.0.json b/analyzers/its/expected/akka.net/S2589-Akka.Cluster.Tools-netstandard2.0.json index afe82424148..7309beeaf96 100644 --- a/analyzers/its/expected/akka.net/S2589-Akka.Cluster.Tools-netstandard2.0.json +++ b/analyzers/its/expected/akka.net/S2589-Akka.Cluster.Tools-netstandard2.0.json @@ -1,11 +1,5 @@ { "Issues": [ - { - "Id": "S2589", - "Message": "Change this condition so that it does not always evaluate to \u0027True\u0027.", - "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/akka.net/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs#L1056", - "Location": "Line 1056 Position 30-45" - }, { "Id": "S2589", "Message": "Change this condition so that it does not always evaluate to \u0027True\u0027.", diff --git a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Invocation.Enumerable.cs b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Invocation.Enumerable.cs index 65ca980235b..382999996d8 100644 --- a/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Invocation.Enumerable.cs +++ b/analyzers/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Invocation.Enumerable.cs @@ -87,18 +87,29 @@ private static ProgramState[] ProcessLinqEnumerableAndQueryable(ProgramState sta return states.Select(x => x.SetOperationConstraint(invocation, ObjectConstraint.NotNull)).ToArray(); } // ElementAtOrDefault is intentionally not supported. It's causing many FPs - else if (name is nameof(Enumerable.FirstOrDefault) or nameof(Enumerable.LastOrDefault) or nameof(Enumerable.SingleOrDefault)) + else if (name is nameof(Enumerable.FirstOrDefault) or nameof(Enumerable.LastOrDefault) or nameof(Enumerable.SingleOrDefault) + && invocation.GetInstance(state).TrackedSymbol(state) is { } instanceSymbol + && GetElementType(instanceSymbol) is { } elementType + && (elementType.IsReferenceType || elementType.IsNullableValueType())) { - return states.SelectMany(x => new List - { - x.SetOperationConstraint(invocation, ObjectConstraint.Null), - x.SetOperationConstraint(invocation, ObjectConstraint.NotNull) - }).ToArray(); + return states.SelectMany(x => ProcessElementOrDefaultMethods(x, invocation, instanceSymbol)).ToArray(); } else { return states; } + + static IEnumerable ProcessElementOrDefaultMethods(ProgramState state, IInvocationOperationWrapper invocation, ISymbol instanceSymbol) => + state[instanceSymbol]?.Constraint() switch + { + CollectionConstraint constraint when constraint == CollectionConstraint.Empty => [state.SetOperationConstraint(invocation, ObjectConstraint.Null)], + CollectionConstraint constraint when constraint == CollectionConstraint.NotEmpty && !HasParameters(invocation.TargetMethod) => [state], + _ => + [ + state.SetOperationConstraint(invocation, ObjectConstraint.Null), + state.SetOperationConstraint(invocation, ObjectConstraint.NotNull) + ], + }; } private static ProgramState[] ProcessElementExistsCheckMethods(ProgramState state, IInvocationOperationWrapper invocation) @@ -109,10 +120,10 @@ private static ProgramState[] ProcessElementExistsCheckMethods(ProgramState stat { CollectionConstraint constraint when constraint == CollectionConstraint.Empty => state.SetOperationConstraint(invocation, BoolConstraint.False).ToArray(), CollectionConstraint constraint when constraint == CollectionConstraint.NotEmpty => - HasNoParameters(invocation.TargetMethod) + !HasParameters(invocation.TargetMethod) ? state.SetOperationConstraint(invocation, BoolConstraint.True).ToArray() : state.ToArray(), - _ when HasNoParameters(invocation.TargetMethod) => + _ when !HasParameters(invocation.TargetMethod) => [ state.SetOperationConstraint(invocation, BoolConstraint.True).SetSymbolConstraint(instanceSymbol, CollectionConstraint.NotEmpty), state.SetOperationConstraint(invocation, BoolConstraint.False).SetSymbolConstraint(instanceSymbol, CollectionConstraint.Empty) @@ -125,9 +136,18 @@ _ when HasNoParameters(invocation.TargetMethod) => }; } return state.ToArray(); - - static bool HasNoParameters(IMethodSymbol symbol) => - (symbol.IsExtensionMethod && symbol.Parameters.Length == 1) - || symbol.Parameters.IsEmpty; } + + private static bool HasParameters(IMethodSymbol symbol) => + symbol.IsExtensionMethod + ? symbol.Parameters.Length > 1 + : !symbol.Parameters.IsEmpty; + + private static ITypeSymbol GetElementType(ISymbol instance) => + instance.GetSymbolType() switch + { + INamedTypeSymbol { TypeArguments: { Length: 1 } typeArguments } => typeArguments.Single(), // Dictionary contain keyvalue pairs which are structs + IArrayTypeSymbol arrayType => arrayType.ElementType, + _ => null + }; } diff --git a/analyzers/tests/SonarAnalyzer.Test/SymbolicExecution/Roslyn/RoslynSymbolicExecutionTest.Invocation.cs b/analyzers/tests/SonarAnalyzer.Test/SymbolicExecution/Roslyn/RoslynSymbolicExecutionTest.Invocation.cs index 0d883f3daa5..5ee4d680105 100644 --- a/analyzers/tests/SonarAnalyzer.Test/SymbolicExecution/Roslyn/RoslynSymbolicExecutionTest.Invocation.cs +++ b/analyzers/tests/SonarAnalyzer.Test/SymbolicExecution/Roslyn/RoslynSymbolicExecutionTest.Invocation.cs @@ -981,10 +981,10 @@ public void Invocation_LinqEnumerableAndQueryable_NullOrNotNull(string expressio [DataTestMethod] // Just a few examples to demonstrate that we don't set ObjectContraint for all [DataRow("Min()")] - [DataRow("ElementAtOrDefault(42);")] - [DataRow("FirstOrDefault();")] - [DataRow("LastOrDefault();")] - [DataRow("SingleOrDefault();")] + [DataRow("ElementAtOrDefault(42)")] + [DataRow("FirstOrDefault()")] + [DataRow("LastOrDefault()")] + [DataRow("SingleOrDefault()")] public void Invocation_LinqEnumerable_Unknown_Int(string expression) { var code = $""" @@ -995,6 +995,102 @@ public void Invocation_LinqEnumerable_Unknown_Int(string expression) validator.TagValue("Value").Should().HaveOnlyConstraint(ObjectConstraint.NotNull); } + [DataTestMethod] + [DataRow("FirstOrDefault()", "object")] + [DataRow("LastOrDefault()", "object")] + [DataRow("SingleOrDefault()", "object")] + [DataRow("FirstOrDefault()", "int?")] + [DataRow("LastOrDefault()", "int?")] + [DataRow("SingleOrDefault()", "int?")] + public void Invocation_ElementOrDefault_CollectionEmpty_ReferenceElementType(string expression, string type) + { + var code = $""" + collection.Clear(); + var value = collection.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"List<{type}> collection").Validator; + validator.TagValue("Value").Should().HaveOnlyConstraint(ObjectConstraint.Null); + } + + [DataTestMethod] + [DataRow("FirstOrDefault()")] + [DataRow("LastOrDefault()")] + [DataRow("SingleOrDefault()")] + public void Invocation_ElementOrDefault_CollectionNotEmpty_ReferenceElementType(string expression) + { + var code = $""" + collection.Add(new object()); + var value = collection.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"List collection").Validator; + validator.TagValue("Value").Should().HaveNoConstraints(); + } + + [DataTestMethod] + [DataRow("FirstOrDefault()")] + [DataRow("LastOrDefault()")] + [DataRow("SingleOrDefault()")] + public void Invocation_ElementOrDefault_CollectionEmpty_ReferenceElementType(string expression) + { + var code = $""" + collection.Clear(); + var value = collection.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"List collection").Validator; + validator.TagValue("Value").Should().HaveOnlyConstraint(ObjectConstraint.Null); + } + + [DataTestMethod] + [DataRow("FirstOrDefault()", true)] + [DataRow("LastOrDefault()", true)] + [DataRow("SingleOrDefault()", true)] + [DataRow("FirstOrDefault()", false)] + [DataRow("LastOrDefault()", false)] + [DataRow("SingleOrDefault()", false)] + public void Invocation_ElementOrDefault_ValueElementType(string expression, bool empty) + { + var code = $""" + collection.{(empty ? "Clear()" : "Add(1)")}; + var value = collection.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"List collection").Validator; + validator.TagValue("Value").Should().HaveOnlyConstraint(ObjectConstraint.NotNull); + } + + [DataTestMethod] + [DataRow("FirstOrDefault(x => x is {})")] + [DataRow("LastOrDefault(x => x is {})")] + [DataRow("SingleOrDefault(x => x is {})")] + public void Invocation_ElementOrDefault_CallWithParameters(string expression) + { + var code = $""" + var value = collection.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"List collection").Validator; + validator.TagValues("Value").Should().HaveCount(2) + .And.ContainSingle(x => x.HasConstraint(ObjectConstraint.Null)) + .And.ContainSingle(x => x.HasConstraint(ObjectConstraint.NotNull)); + } + + [DataTestMethod] + [DataRow("FirstOrDefault()")] + [DataRow("LastOrDefault()")] + [DataRow("SingleOrDefault()")] + public void Invocation_ElementOrDefault_Dictionary(string expression) // Dictionaries always return KeyValuePair which is a value type + { + var code = $""" + var value = dict.{expression}; + Tag("Value", value); + """; + var validator = SETestContext.CreateCS(code, $"Dictionary dict").Validator; + validator.TagValue("Value").Should().HaveOnlyConstraint(ObjectConstraint.NotNull); + } + [DataTestMethod] // Just a few examples to demonstrate that we don't set ObjectContraint for all [DataRow("First()")] [DataRow("ElementAtOrDefault(42);")] diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/SymbolicExecution/Roslyn/NullPointerDereference.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/SymbolicExecution/Roslyn/NullPointerDereference.cs index 715bb12caa6..f13762a6b5e 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/SymbolicExecution/Roslyn/NullPointerDereference.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/SymbolicExecution/Roslyn/NullPointerDereference.cs @@ -2085,7 +2085,7 @@ void Method(Exception[] array) if (array.Any()) { Exception exception = array.FirstOrDefault(); - Console.WriteLine(exception.Message); // Noncompliant - FP + Console.WriteLine(exception.Message); // Compliant - we know that array is not empty } } }