Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Do not suggest 'Create file' code action for broken heading references #320

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions Marksman/CodeActions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ open Marksman.Index
open Marksman.Folder
open Marksman.Refs
open Marksman.Toc
open Marksman.Structure
open Marksman.Syms

let private logger = LogProvider.getLoggerByName "CodeActions"

Expand Down Expand Up @@ -125,17 +127,23 @@ let createMissingFile

monad' {
let! atPos = Doc.index doc |> Index.linkAtPos pos
let refs = Dest.tryResolveElement folder doc atPos

// Early return if the file exists
do! guard (Seq.isEmpty refs)
// Extract a potential xref to another doc. We should extract only the doc part to ensure
// that empty list of references means that the file doesn't exist
let! symAtPos = doc.Structure |> Structure.tryFindSymbolForConcrete atPos

let! name =
match doc.Structure |> Structure.Structure.tryFindSymbolForConcrete atPos with
| Some(Syms.Sym.Ref(Syms.CrossRef r)) -> Some r.Doc
let! docAtPos =
match symAtPos with
| Sym.Ref(CrossRef r) -> Some(r.Doc)
| _ -> None

let! internPath = InternName.tryAsPath { name = name; src = doc.Id }
let docRefAtPos = Sym.Ref(CrossRef(CrossDoc docAtPos))
let refs = Dest.tryResolveSym folder doc docRefAtPos

// Early return if the file exists
do! guard (Seq.isEmpty refs)

let! internPath = InternName.tryAsPath { name = docAtPos; src = doc.Id }

let relPath =
InternPath.toRel internPath
Expand Down
2 changes: 1 addition & 1 deletion Marksman/Refs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ module Dest =
| Some(IntraRef(IntraSection _)) -> Implicit destDoc
| _ -> failwith $"Link kind cannot be determined for {srcSym} symbol"

let private tryResolveSym (folder: Folder) (doc: Doc) (srcSym: Sym) : seq<Dest> =
let tryResolveSym (folder: Folder) (doc: Doc) (srcSym: Sym) : seq<Dest> =
let complStyle = (Folder.configOrDefault folder).ComplWikiStyle()

let scopedSym = Sym.scopedToDoc doc.Id srcSym
Expand Down
1 change: 1 addition & 0 deletions Marksman/Refs.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ module Dest =
val scope: Dest -> Range
val location: Dest -> Location

val tryResolveSym: Folder -> Doc -> Syms.Sym -> seq<Dest>
val tryResolveElement: Folder -> Doc -> Element -> seq<Dest>
val findElementRefs: bool -> Folder -> Doc -> Element -> seq<Doc * Element>
36 changes: 36 additions & 0 deletions Tests/CodeActionTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Marksman.CodeActionTests

open Ionide.LanguageServerProtocol.Types
open Xunit

open Marksman.Helpers
open Marksman.Misc

module CreateMissingFileTests =
[<Fact>]
let shouldCreateWhenNoFileExists () =
let doc1 = FakeDoc.Mk([| "# Doc 1"; "## Sub 1" |], path = "doc1.md")
let doc2 = FakeDoc.Mk([| "[[doc3]]" |], path = "doc2.md")
let folder = FakeFolder.Mk([ doc1; doc2 ])

let caCtx = { Diagnostics = [||]; Only = None; TriggerKind = None }

let ca =
CodeActions.createMissingFile (Range.Mk(0, 3, 0, 3)) caCtx doc2 folder

match ca with
| Some { name = "Create `doc3.md`" } -> Assert.True(true)
| _ -> Assert.True(false)

[<Fact>]
let shouldNotCreateWhenRefBrokenButFileExists () =
let doc1 = FakeDoc.Mk([| "# Doc 1"; "## Sub 1" |], path = "doc1.md")
let doc2 = FakeDoc.Mk([| "[[doc1#Sub 2]]" |], path = "doc2.md")
let folder = FakeFolder.Mk([ doc1; doc2 ])

let caCtx = { Diagnostics = [||]; Only = None; TriggerKind = None }

let ca =
CodeActions.createMissingFile (Range.Mk(0, 3, 0, 3)) caCtx doc2 folder

Assert.Equal(None, ca)
1 change: 1 addition & 0 deletions Tests/Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<Compile Include="ConnTest.fs" />
<Compile Include="MMapTests.fs" />
<Compile Include="LensesTests.fs" />
<Compile Include="CodeActionTests.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

Expand Down
Loading