diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs index b6b13608cb1..ac0b952f65f 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs @@ -55,21 +55,26 @@ type internal AddOpenCodeFixProvider [] (assemblyContentPr // attribute, shouldn't be here | line when line.StartsWith "[<" && line.EndsWith ">]" -> - let moduleDeclLineNumber = + let moduleDeclLineNumberOpt = sourceText.Lines |> Seq.skip insertionLineNumber - |> Seq.findIndex (fun line -> line.ToString().Contains "module") - // add back the skipped lines - |> fun i -> insertionLineNumber + i + |> Seq.tryFindIndex (fun line -> line.ToString().Contains "module") - let moduleDeclLineText = sourceText.Lines[ moduleDeclLineNumber ].ToString().Trim() + match moduleDeclLineNumberOpt with + // implicit top level module + | None -> insertionLineNumber, $"{margin}open {ns}{br}{br}" + // explicit top level module + | Some number -> + // add back the skipped lines + let moduleDeclLineNumber = insertionLineNumber + number + let moduleDeclLineText = sourceText.Lines[ moduleDeclLineNumber ].ToString().Trim() - if moduleDeclLineText.EndsWith "=" then - insertionLineNumber, $"{margin}open {ns}{br}{br}" - else - moduleDeclLineNumber + 2, $"{margin}open {ns}{br}{br}" + if moduleDeclLineText.EndsWith "=" then + insertionLineNumber, $"{margin}open {ns}{br}{br}" + else + moduleDeclLineNumber + 2, $"{margin}open {ns}{br}{br}" - // something else, shot in the dark + // implicit top level module | _ -> insertionLineNumber, $"{margin}open {ns}{br}{br}" | ScopeKind.Namespace -> insertionLineNumber + 3, $"{margin}open {ns}{br}{br}" diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOffTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOffTests.fs index 297554f3784..d3897828292 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOffTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOffTests.fs @@ -159,7 +159,7 @@ let ``Fixes FS0039 for missing opens - nested module`` () = Assert.Equal(expected, actual) [] -let ``Fixes FS0039 for missing opens - module has attributes`` () = +let ``Fixes FS0039 for missing opens - explicit module has attributes`` () = let code = """ [] @@ -187,6 +187,33 @@ Console.WriteLine 42 Assert.Equal(expected, actual) +[] +let ``Fixes FS0039 for missing opens - implicit module has attributes`` () = + let code = + """ +[] +type MyType() = + let now = DateTime.Now +""" + + let expected = + Some + { + Message = "open System" + FixedCode = + """ +open System + +[] +type MyType() = + let now = DateTime.Now +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + // TODO: the open statement should actually be within the module [] let ``Fixes FS0039 for missing opens - nested module has attributes`` () = diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOnTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOnTests.fs index ac95de440d4..185fd8390d1 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOnTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/AddOpenOnTopOnTests.fs @@ -153,7 +153,7 @@ module Module1 = Assert.Equal(expected, actual) [] -let ``Fixes FS0039 for missing opens - module has attributes`` () = +let ``Fixes FS0039 for missing opens - explicit module has attributes`` () = let code = """ [] @@ -181,6 +181,33 @@ Console.WriteLine 42 Assert.Equal(expected, actual) +[] +let ``Fixes FS0039 for missing opens - implicit module has attributes`` () = + let code = + """ +[] +type MyType() = + let now = DateTime.Now +""" + + let expected = + Some + { + Message = "open System" + FixedCode = + """ +open System + +[] +type MyType() = + let now = DateTime.Now +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + [] let ``Fixes FS0039 for missing opens - nested module has attributes`` () = let code =