Skip to content

Commit ed10ddd

Browse files
Add misc unused opens tests
1 parent 9b4a7ce commit ed10ddd

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs

+113
Original file line numberDiff line numberDiff line change
@@ -5660,6 +5660,119 @@ type UseTheThings(i:int) =
56605660
(((37, 10), (37, 21)), "open type FSharpEnum2 // Unused, should appear.")]
56615661
unusedOpensData |> shouldEqual expected
56625662

5663+
[<Theory>]
5664+
[<InlineData("""// 1. Auto-open type extension.
5665+
// https://github.com/dotnet/fsharp/issues/17629
5666+
module Module
5667+
5668+
type T =
5669+
static member A = 99
5670+
5671+
[<AutoOpen>]
5672+
module M =
5673+
type T with
5674+
static member Lol = 3
5675+
5676+
// Shows as unused; the unused opens analyzer will suggest removing it…
5677+
open type T
5678+
5679+
// …Even though it's used.
5680+
let lol = Lol
5681+
""")>]
5682+
[<InlineData("""// 2. Open type on fully-qualified union type.
5683+
// https://github.com/dotnet/fsharp/issues/17629
5684+
module M =
5685+
type E = A | B
5686+
5687+
open type M.E // Considered unused, even though it is.
5688+
5689+
let f x =
5690+
match x with
5691+
| A -> ()
5692+
| B -> ()
5693+
""")>]
5694+
[<InlineData("""// 3. Open namespace with auto-opened type.
5695+
// https://github.com/dotnet/fsharp/issues/17929
5696+
namespace SomeOtherNamespace
5697+
5698+
[<AutoOpen>]
5699+
type SomeUnusedType =
5700+
static member y = 1
5701+
5702+
namespace Test
5703+
5704+
open SomeOtherNamespace
5705+
5706+
type UseTheThings(i:int) =
5707+
member x.UseSomeOtherNamespaceTypeMember() = y
5708+
""")>]
5709+
let ``Unused opens misc`` fileSource1Text =
5710+
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
5711+
let base2 = getTemporaryFileName ()
5712+
let dllName = Path.ChangeExtension(base2, ".dll")
5713+
let projFileName = Path.ChangeExtension(base2, ".fsproj")
5714+
let fileSource1 = SourceText.ofString fileSource1Text
5715+
FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text)
5716+
5717+
let fileNames = [|fileName1|]
5718+
let args = mkProjectCommandLineArgs (dllName, [])
5719+
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
5720+
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
5721+
5722+
let fileCheckResults =
5723+
keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate
5724+
|> function
5725+
| _, FSharpCheckFileAnswer.Succeeded(res) -> res
5726+
| _ -> failwithf "Parsing aborted unexpectedly..."
5727+
let lines = FileSystem.OpenFileForReadShim(fileName1).ReadAllLines()
5728+
let unusedOpens = UnusedOpens.getUnusedOpens (fileCheckResults, (fun i -> lines[i-1])) |> Async.RunImmediate
5729+
let unusedOpensData = [ for uo in unusedOpens -> tups uo, lines[uo.StartLine-1] ]
5730+
unusedOpensData |> shouldEqual []
5731+
5732+
[<Fact>]
5733+
let ``Unused opens shadowing`` () =
5734+
let fileSource1Text =
5735+
"""
5736+
// https://github.com/dotnet/fsharp/issues/16226
5737+
namespace Case2
5738+
5739+
module RecordA =
5740+
type Record = { Foo: string }
5741+
5742+
module RecordB =
5743+
type Record = { Bar: string }
5744+
5745+
module Use =
5746+
open RecordB // Not required.
5747+
open RecordA // Required.
5748+
open RecordB // Required.
5749+
5750+
let convertBToA (recordB: Record) =
5751+
{ Foo = recordB.Bar }
5752+
"""
5753+
5754+
let fileName1 = Path.ChangeExtension(getTemporaryFileName (), ".fs")
5755+
let base2 = getTemporaryFileName ()
5756+
let dllName = Path.ChangeExtension(base2, ".dll")
5757+
let projFileName = Path.ChangeExtension(base2, ".fsproj")
5758+
let fileSource1 = SourceText.ofString fileSource1Text
5759+
FileSystem.OpenFileForWriteShim(fileName1).Write(fileSource1Text)
5760+
5761+
let fileNames = [|fileName1|]
5762+
let args = mkProjectCommandLineArgs (dllName, [])
5763+
let keepAssemblyContentsChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler)
5764+
let options = { keepAssemblyContentsChecker.GetProjectOptionsFromCommandLineArgs (projFileName, args) with SourceFiles = fileNames }
5765+
5766+
let fileCheckResults =
5767+
keepAssemblyContentsChecker.ParseAndCheckFileInProject(fileName1, 0, fileSource1, options) |> Async.RunImmediate
5768+
|> function
5769+
| _, FSharpCheckFileAnswer.Succeeded(res) -> res
5770+
| _ -> failwithf "Parsing aborted unexpectedly..."
5771+
let lines = FileSystem.OpenFileForReadShim(fileName1).ReadAllLines()
5772+
let unusedOpens = UnusedOpens.getUnusedOpens (fileCheckResults, (fun i -> lines[i-1])) |> Async.RunImmediate
5773+
let unusedOpensData = [ for uo in unusedOpens -> tups uo, lines[uo.StartLine-1] ]
5774+
unusedOpensData |> shouldEqual [(((12, 9), (12, 16)), " open RecordB // Not required.")]
5775+
56635776
[<Fact>]
56645777
let ``Unused opens smoke test auto open`` () =
56655778

0 commit comments

Comments
 (0)