diff --git a/src/FSharpLint.Core/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs b/src/FSharpLint.Core/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs index 601d476de..aa854f1a5 100644 --- a/src/FSharpLint.Core/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs +++ b/src/FSharpLint.Core/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs @@ -30,15 +30,44 @@ let hasEntryPoint (checkFileResults: FSharpCheckFileResults) (maybeProjectCheckR | None -> false -let excludedProjectNames = [ "test"; "console" ] +let private projectNamesUnlikelyToBeLibraries = + [ + "tests" + "test" + "testing" + "console" + "CLI" + "TUI" + ] + |> Seq.map (fun name -> name.ToLowerInvariant()) + +let private possibleProjectNameSegmentSeparators = + [| + '.' + '_' + '-' + |] let howLikelyProjectIsLibrary (projectFileName: string): LibraryHeuristicResultByProjectName = - let nameSegments = Helper.Naming.QuickFixes.splitByCaseChange projectFileName - if nameSegments |> Seq.contains "Lib" then + let libraryAbbrev = "lib" + let nameSegments = + Helper.Naming.QuickFixes.splitByCaseChange projectFileName + |> Seq.map (fun segment -> segment.ToLowerInvariant()) + if nameSegments |> Seq.contains libraryAbbrev then Likely - elif excludedProjectNames |> List.exists (fun name -> projectFileName.ToLowerInvariant().Contains name) then + elif + nameSegments + |> Seq.exists ( + fun segment -> + let subSegments = segment.Split possibleProjectNameSegmentSeparators + subSegments + |> Seq.exists (fun subSegment -> + projectNamesUnlikelyToBeLibraries + |> Seq.exists (fun noLibName -> noLibName = subSegment) + ) + ) then Unlikely - elif projectFileName.ToLowerInvariant().EndsWith "lib" then + elif projectFileName.ToLowerInvariant().EndsWith libraryAbbrev then Likely else Uncertain diff --git a/tests/FSharpLint.Core.Tests/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs b/tests/FSharpLint.Core.Tests/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs index 65e95c40a..f7ad9fddf 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Smells/NoAsyncRunSynchronouslyInLibrary.fs @@ -134,37 +134,102 @@ let Foo() = [] type TestNoAsyncRunSynchronouslyInLibraryHeuristic() = + + [] + member this.``Unlikely to be library if contains "tests" in name``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "IntegrationTests" + ) + + [] + member this.``Unlikely to be library if contains "testing" in name``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "UnitTesting" + ) + [] member this.``Unlikely to be library if contains "test" in name``() = Assert.AreEqual( - howLikelyProjectIsLibrary "TestProject", - LibraryHeuristicResultByProjectName.Unlikely + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "TestSuite" ) [] member this.``Unlikely to be library if contains "console" in name``() = Assert.AreEqual( - howLikelyProjectIsLibrary "FooConsole", - LibraryHeuristicResultByProjectName.Unlikely + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "FooConsole" ) [] member this.``Likely to be library if contains Contains "Lib" as a PascalCase segment``() = Assert.AreEqual( - howLikelyProjectIsLibrary "LibFoo", - LibraryHeuristicResultByProjectName.Likely + LibraryHeuristicResultByProjectName.Likely, + howLikelyProjectIsLibrary "LibFoo" ) [] member this.``Uncertain if contains contains "Lib" but not as a PascalCase segment``() = Assert.AreEqual( - howLikelyProjectIsLibrary "LibreOfficeProg", - LibraryHeuristicResultByProjectName.Uncertain + LibraryHeuristicResultByProjectName.Uncertain, + howLikelyProjectIsLibrary "LibreOfficeProg" ) [] member this.``Likely to be library if contains ends with "lib" (case-insensitive)``() = Assert.AreEqual( - howLikelyProjectIsLibrary "FooLib", - LibraryHeuristicResultByProjectName.Likely + LibraryHeuristicResultByProjectName.Likely, + howLikelyProjectIsLibrary "FooLib" + ) + + [] + member this.``Unlikely to be library if contains "CLI" in name``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "FooCLI" + ) + + [] + member this.``Uncertain to be library if contains "cli" in name not related to CLI``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Uncertain, + howLikelyProjectIsLibrary "InclinedDriver" + ) + + [] + member this.``Unlikely to be library if contains "TUI" in name``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "FooTUI" + ) + + [] + member this.``Likely to be library if it starts with "lib", e.g. camelCase``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Likely, + howLikelyProjectIsLibrary "libFoo" + ) + + [] + member this.``Unlikely to be library if it contains "console", but segments are separated by dots``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "foo.console.app" ) + + [] + member this.``Unlikely to be library if it contains "console", but segments are separated by dashes``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "foo-console-app" + ) + + [] + member this.``Unlikely to be library if it contains "console", but segments are separated by underscores``() = + Assert.AreEqual( + LibraryHeuristicResultByProjectName.Unlikely, + howLikelyProjectIsLibrary "foo_console_app" + ) +