From fa877f3e4061cea088c3b0570a0dc92e6a8b9000 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Thu, 9 Jul 2015 00:37:28 +0200 Subject: [PATCH 01/11] Adds methods to link other types using type full name Adds basic test for linking types. Adds methods to collect all indirect links, find the type references and add the links to the found types. --- src/FSharp.MetadataFormat/Main.fs | 48 +++++++++++++++++++ tests/FSharp.MetadataFormat.Tests/Tests.fs | 12 ++++- .../files/FsLib/Library2.fs | 6 +++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index 6631b06da..d2edcff80 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -563,6 +563,53 @@ module Reader = let str = full.ToString() Comment.Create(str, str, [KeyValuePair("", str)]) + /// Returns all indirect links in a specified span node + let rec collectSpanIndirectLinks span = seq { + match span with + | IndirectLink(_, _, key) -> yield key + | Matching.SpanLeaf _ -> () + | Matching.SpanNode(_, spans) -> + for s in spans do yield! collectSpanIndirectLinks s } + + /// Returns all indirect links in the specified paragraph node + let rec collectParagraphIndirectLinks par = seq { + match par with + | Matching.ParagraphLeaf _ -> () + | Matching.ParagraphNested(_, pars) -> + for ps in pars do + for p in ps do yield! collectParagraphIndirectLinks p + | Matching.ParagraphSpans(_, spans) -> + for s in spans do yield! collectSpanIndirectLinks s } + + /// Returns whether the link is not included in the document defined links + let linkNotDefined (doc: LiterateDocument) (link:string) = + [ link; link.Replace("\r\n", ""); link.Replace("\r\n", " "); + link.Replace("\n", ""); link.Replace("\n", " ") ] + |> Seq.map (fun key -> not(doc.DefinedLinks.ContainsKey(key)) ) + |> Seq.reduce (fun a c -> a && c) + + /// Returns a tuple of the undefined link and its Cref if it exists + let getTypeLink (ctx:ReadingContext) undefinedLink = + // Append 'T:' to try to get the link from urlmap + match ctx.UrlMap.ResolveCref ("T:" + undefinedLink) with + | Some cRef -> Some (undefinedLink, cRef) + | None -> None + + /// Ads a link to a Type to the document defined links + let addLinkToType (doc: LiterateDocument) link = + match link with + | Some(k, v) -> doc.DefinedLinks.Add(k, (v.ReferenceLink, Some v.NiceName)) |> ignore + | None -> () + + /// Adds the missiing links to types to the document defined links + let addMissingLinkToTypes ctx (doc: LiterateDocument) = + doc.Paragraphs + |> Seq.collect collectParagraphIndirectLinks + |> Seq.filter (linkNotDefined doc) + |> Seq.map (getTypeLink ctx) + |> Seq.iter (addLinkToType doc) + doc + let readCommentAndCommands (ctx:ReadingContext) xmlSig = match ctx.XmlMemberLookup(xmlSig) with | None -> @@ -590,6 +637,7 @@ module Reader = Literate.ParseMarkdownString ( text, path=Path.Combine(ctx.AssemblyPath, "docs.fsx"), formatAgent=ctx.FormatAgent, compilerOptions=ctx.CompilerOptions ) + |> (addMissingLinkToTypes ctx) cmds :> IDictionary<_, _>, readMarkdownComment doc else let cmds = new System.Collections.Generic.Dictionary<_, _>() diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index 343ee70d3..65e54d162 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -420,4 +420,14 @@ let ``MetadataFormat generates module link in nested types``() = // Check that nested submodules have links to its module files.["fslib-nested-submodule.html"] |> should contain "Parent Module:" files.["fslib-nested-submodule.html"] |> should contain "Nested" - \ No newline at end of file + +[] +let ``Link to other types``() = + let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" + let output = getOutputDir() + MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) + let fileNames = Directory.GetFiles(output) + let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] + + // Check that a link to MyType exists + files.["fslib-nested.html"] |> should contain "This function returns a FsLib.Nested.MyType" diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index 4f9cc533e..bd96354f4 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -22,6 +22,12 @@ module Nested = /// Very nested member member x.Member = "" + /// This is My type + type MyType = int + + /// This function returns a [FsLib.Nested.MyType] multiplied by 2. + let f x :MyType = x * 2 + type ITest_Issue229 = abstract member Name : string type Test_Issue229 (name) = From 525618ef8a4ad1183d617ed7385d4102843d6660 Mon Sep 17 00:00:00 2001 From: Edgar Hernandez Date: Tue, 28 Jul 2015 01:06:03 +0200 Subject: [PATCH 02/11] Add failing test for link to type with simple name --- tests/FSharp.MetadataFormat.Tests/Tests.fs | 71 ++++++++++--------- .../files/FsLib/Library2.fs | 17 +++-- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index 65e54d162..ac595c708 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -15,19 +15,19 @@ open NUnit.Framework open FSharp.MetadataFormat // -------------------------------------------------------------------------------------- -// Run the metadata formatter on sample project +// Run the metadata formatter on sample project // -------------------------------------------------------------------------------------- let (@@) a b = Path.Combine(a, b) -let root = __SOURCE_DIRECTORY__ +let root = __SOURCE_DIRECTORY__ -let getOutputDir() = +let getOutputDir() = let tempFile = Path.GetTempFileName() File.Delete(tempFile) Directory.CreateDirectory(tempFile).FullName -let layoutRoots = +let layoutRoots = [ root @@ "../../misc/templates" root @@ "../../misc/templates/reference" ] @@ -40,7 +40,7 @@ let info = "root", "http://tpetricek.github.io/FSharp.FSharp.ProjectScaffold" ] [] -let ``MetadataFormat works on sample Deedle assembly``() = +let ``MetadataFormat works on sample Deedle assembly``() = let library = root @@ "files" @@ "Deedle.dll" let output = getOutputDir() MetadataFormat.Generate @@ -48,10 +48,10 @@ let ``MetadataFormat works on sample Deedle assembly``() = sourceRepo = "https://github.com/BlueMountainCapital/Deedle/tree/master/", sourceFolder = "c:/dev/FSharp.DataFrame") let files = Directory.GetFiles(output) - + let optIndex = files |> Seq.tryFind (fun s -> s.EndsWith "index.html") optIndex.IsSome |> shouldEqual true - + let optSeriesMod = files |> Seq.tryFind (fun s -> s.Contains "seriesmodule") optSeriesMod.IsSome |> shouldEqual true @@ -61,7 +61,7 @@ let ``MetadataFormat works on sample Deedle assembly``() = // Ignore by default to make tests run reasonably fast [] -let ``MetadataFormat works on sample FAKE assembly``() = +let ``MetadataFormat works on sample FAKE assembly``() = let library = root @@ "files" @@ "FAKE" @@ "FakeLib.dll" let output = getOutputDir() MetadataFormat.Generate(library, output, layoutRoots, info) @@ -72,8 +72,8 @@ let removeWhiteSpace (str:string) = str.Replace("\n", "").Replace("\r", "").Replace(" ", "") [] -let ``MetadataFormat works on two sample F# assemblies``() = - let libraries = +let ``MetadataFormat works on two sample F# assemblies``() = + let libraries = [ root @@ "files/FsLib/bin/Debug" @@ "FsLib1.dll" root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" ] let output = getOutputDir() @@ -105,7 +105,7 @@ let ``MetadataFormat works on two sample F# assemblies``() = files.["fslib-record.html"] |> should contain "Foo2()" files.["fslib-record.html"] |> should contain "Signature: unit -> int" files.["fslib-class.html"] |> should contain "new()" - files.["fslib-class.html"] |> should contain "Signature: unit -> Class" + files.["fslib-class.html"] |> should contain "Signature: unit -> Class" // Check that properties are correctly generated (#114) files.["fslib-class.html"] |> removeWhiteSpace |> should notContain ">Member(arg1)<" @@ -113,20 +113,20 @@ let ``MetadataFormat works on two sample F# assemblies``() = files.["fslib-class.html"] |> removeWhiteSpace |> should contain ">Member<" files.["fslib-class.html"] |> should notContain "Signature: unit -> int" files.["fslib-class.html"] |> should contain "Signature: int" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif [] -let ``MetadataFormat generates Go to GitHub source links``() = - let libraries = +let ``MetadataFormat generates Go to GitHub source links``() = + let libraries = [ root @@ "files/FsLib/bin/Debug" @@ "FsLib1.dll" root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" ] let output = getOutputDir() printfn "Output: %s" output MetadataFormat.Generate - ( libraries, output, layoutRoots, info, libDirs = [root @@ "../../lib"], + ( libraries, output, layoutRoots, info, libDirs = [root @@ "../../lib"], sourceRepo = "https://github.com/tpetricek/FSharp.Formatting/tree/master", sourceFolder = root @@ "../.." ) let fileNames = Directory.GetFiles(output) @@ -137,7 +137,7 @@ let ``MetadataFormat generates Go to GitHub source links``() = files.["fslib-record.html"] |> should contain "https://github.com/tpetricek/FSharp.Formatting/tree/master/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library1.fs#L" files.["fslib-union.html"] |> should contain "github-link" files.["fslib-union.html"] |> should contain "https://github.com/tpetricek/FSharp.Formatting/tree/master/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library1.fs#L" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif @@ -247,27 +247,27 @@ let ``MetadataFormat test that csharp (publiconly) support works``() = files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Event" - - + + files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Method") files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Property") files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Event") files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Sample_Class" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Event" - + files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Method") files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Property") files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Event") - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif - + [] [] let ``MetadataFormat test that csharp support works``() = @@ -301,29 +301,29 @@ let ``MetadataFormat test that csharp support works``() = files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Event" - - + + files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Event" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Sample_Class" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Event" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Event" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif [] -let ``MetadataFormat process XML comments in two sample F# assemblies``() = - let libraries = +let ``MetadataFormat process XML comments in two sample F# assemblies``() = + let libraries = [ root @@ "files/TestLib/bin/Debug" @@ "TestLib1.dll" root @@ "files/TestLib/bin/Debug" @@ "TestLib2.dll" ] let output = getOutputDir() @@ -343,7 +343,7 @@ let ``MetadataFormat process XML comments in two sample F# assemblies``() = files.["fslib-nested-submodule.html"] |> should contain "Very nested field" [] -let ``MetadataFormat highlights code snippets in Markdown comments``() = +let ``MetadataFormat highlights code snippets in Markdown comments``() = let library = root @@ "files/TestLib/bin/Debug" @@ "TestLib1.dll" let output = getOutputDir() MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) @@ -360,7 +360,7 @@ let ``MetadataFormat handles c# dlls`` () = MetadataFormat.Generate ( library, output, layoutRoots, info, libDirs = [root @@ "../../lib"]) let files = Directory.GetFiles(output) - + let optIndex = files |> Seq.tryFind (fun s -> s.EndsWith "index.html") optIndex.IsSome |> shouldEqual true @@ -386,19 +386,19 @@ let ``MetadataFormat processes C# properties on types and includes xml comments MetadataFormat.Generate ( library, output, layoutRoots, info, libDirs = [root @@ "../../lib"]) let fileNames = Directory.GetFiles(output) - let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - + let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] + files.["manoli-utils-csharpformat-clikeformat.html"] |> should contain "CommentRegEx" files.["manoli-utils-csharpformat-clikeformat.html"] |> should contain "Regular expression string to match single line and multi-line" [] -let ``MetadataFormat generates module link in nested types``() = +let ``MetadataFormat generates module link in nested types``() = let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" let output = getOutputDir() MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) let fileNames = Directory.GetFiles(output) let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - + // Check that the modules and type files have namespace information files.["fslib-class.html"] |> should contain "Namespace: FsLib" files.["fslib-nested.html"] |> should contain "Namespace: FsLib" @@ -431,3 +431,4 @@ let ``Link to other types``() = // Check that a link to MyType exists files.["fslib-nested.html"] |> should contain "This function returns a FsLib.Nested.MyType" + files.["fslib-nested.html"] |> should contain "This function returns a OtherType" diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index bd96354f4..d2d7fdea5 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -1,14 +1,14 @@ namespace FsLib /// Sample class -type Class() = +type Class() = /// Readonly int property member x.Member = 0 /// Nested module -module Nested = +module Nested = /// Somewhat nested module - module Submodule = + module Submodule = /// Very nested field let supernested = 42 @@ -18,16 +18,21 @@ module Nested = member x.Member = "" /// Somewhat nested type - type NestedType() = + type NestedType() = /// Very nested member member x.Member = "" /// This is My type type MyType = int + type OtherType = int + /// This function returns a [FsLib.Nested.MyType] multiplied by 2. let f x :MyType = x * 2 + /// This function returns a [OtherType] multiplied by 3. + let f2 x :OtherType = x * 3 + type ITest_Issue229 = abstract member Name : string type Test_Issue229 (name) = @@ -36,10 +41,10 @@ type Test_Issue229 (name) = interface ITest_Issue229 with /// interface comment - member x.Name = name + member x.Name = name type Test_Issue287 () = /// Function Foo! abstract member Foo: int-> unit /// Empty function for signature - default x.Foo a = () \ No newline at end of file + default x.Foo a = () From 56a38e8e42361e65a30b82d361af1ef96806a43e Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Wed, 29 Jul 2015 15:35:20 +0200 Subject: [PATCH 03/11] Added new Dictionary to lookup TypeCref by LogicalName --- src/FSharp.MetadataFormat/Main.fs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index 2eb4d6729..cc035c27b 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -733,6 +733,7 @@ module Reader = let usedNames = Dictionary<_, _>() let registeredEntities = Dictionary<_, _>() let entityLookup = Dictionary<_, _>() + let niceNameEntityLookup = Dictionary<_, _>() let nameGen (name:string) = let nice = (toReplace |> Seq.fold (fun (s:string) (inv, repl) -> s.Replace(inv, repl)) name) @@ -750,6 +751,9 @@ module Reader = if (not (System.String.IsNullOrEmpty xmlsig)) then assert (xmlsig.StartsWith("T:")) entityLookup.[xmlsig.Substring(2)] <- entity + if (not(niceNameEntityLookup.ContainsKey(entity.LogicalName))) then + niceNameEntityLookup.[entity.LogicalName] <- List<_>() + niceNameEntityLookup.[entity.LogicalName].Add(entity) for nested in entity.NestedEntities do registerEntity nested let getUrl (entity:FSharpEntity) = @@ -778,7 +782,11 @@ module Reader = match entityLookup.TryGetValue(typeName) with | true, entity -> Some { IsInternal = true; ReferenceLink = sprintf "%s.html" (getUrl entity); NiceName = entity.LogicalName } - | _ -> None + | _ -> + match niceNameEntityLookup.TryGetValue(typeName) with + | true, entityList -> + if entityList.Count = 1 then Some{ IsInternal = true; ReferenceLink = sprintf "%s.html" (getUrl entityList.[0]); NiceName = entityList.[0].LogicalName } else None + | _ -> None let resolveCref (cref:string) = if (cref.Length <= 2) then invalidArg "cref" (sprintf "the given cref: '%s' is invalid!" cref) From 3cf1c123cefbeabb64deb30494aef7ba494ba8f8 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Wed, 29 Jul 2015 17:07:04 +0200 Subject: [PATCH 04/11] Restrict links to only internal types. Added more test cases for - Types with duplicated names - Inexistent types Restricted links to be only internal because if the type is not found in `UrlMap.ResolveCref`, the url returned is a URL to msdn documentation. --- src/FSharp.MetadataFormat/Main.fs | 2 +- tests/FSharp.MetadataFormat.Tests/Tests.fs | 16 +++++++++++++++- .../files/FsLib/Library2.fs | 13 +++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index cc035c27b..daea95de2 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -593,7 +593,7 @@ module Reader = let getTypeLink (ctx:ReadingContext) undefinedLink = // Append 'T:' to try to get the link from urlmap match ctx.UrlMap.ResolveCref ("T:" + undefinedLink) with - | Some cRef -> Some (undefinedLink, cRef) + | Some cRef -> if cRef.IsInternal then Some (undefinedLink, cRef) else None | None -> None /// Ads a link to a Type to the document defined links diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index ac595c708..b0fec1151 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -429,6 +429,20 @@ let ``Link to other types``() = let fileNames = Directory.GetFiles(output) let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - // Check that a link to MyType exists + // Check that a link to MyType exists when using Full Name of the type files.["fslib-nested.html"] |> should contain "This function returns a FsLib.Nested.MyType" + + // Check that a link to OtherType exists when using Logical Name of the type only files.["fslib-nested.html"] |> should contain "This function returns a OtherType" + + // Check that a link to a module is created when using Logical Name only + files.["fslib-duplicatedtypename.html"] |> should contain "This type name will be duplicated in Nested" + + // Check that a link to a type with a duplicated name is created when using full name + files.["fslib-nested-duplicatedtypename.html"] |> should contain "This type has the same name as FsLib.DuplicatedTypeName" + + // Check that a link to a type with a duplicated name is not created when using Logical name only + files.["fslib-nested.html"] |> should contain "This function returns a [DuplicatedTypeName] multiplied by 4." + + // Check that a link to a type with a duplicated name is not created when using Logical name only + files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." \ No newline at end of file diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index d2d7fdea5..1a14b1110 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -1,5 +1,8 @@ namespace FsLib +/// This type name will be duplicated in [Nested] +type DuplicatedTypeName = int + /// Sample class type Class() = /// Readonly int property @@ -25,14 +28,24 @@ module Nested = /// This is My type type MyType = int + /// This is other type type OtherType = int + /// This type has the same name as [FsLib.DuplicatedTypeName] + type DuplicatedTypeName = int + /// This function returns a [FsLib.Nested.MyType] multiplied by 2. let f x :MyType = x * 2 /// This function returns a [OtherType] multiplied by 3. let f2 x :OtherType = x * 3 + /// This function returns a [DuplicatedTypeName] multiplied by 4. + let f3 x :OtherType = x * 4 + + /// This function returns a [InexistentTypeName] multiplied by 5. + let f4 x :OtherType = x * 5 + type ITest_Issue229 = abstract member Name : string type Test_Issue229 (name) = From d72f4c31b3e78b96986e5cbbf17695cd87706c24 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Thu, 8 Oct 2015 17:01:21 +0200 Subject: [PATCH 05/11] Fixed bad merge. --- tests/FSharp.MetadataFormat.Tests/Tests.fs | 68 ++++++++----------- .../files/FsLib/Library2.fs | 10 +-- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index bf8b3cbf7..53ee26bb0 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -15,19 +15,19 @@ open NUnit.Framework open FSharp.MetadataFormat // -------------------------------------------------------------------------------------- -// Run the metadata formatter on sample project +// Run the metadata formatter on sample project // -------------------------------------------------------------------------------------- let (@@) a b = Path.Combine(a, b) -let root = __SOURCE_DIRECTORY__ +let root = __SOURCE_DIRECTORY__ -let getOutputDir() = +let getOutputDir() = let tempFile = Path.GetTempFileName() File.Delete(tempFile) Directory.CreateDirectory(tempFile).FullName -let layoutRoots = +let layoutRoots = [ root @@ "../../misc/templates" root @@ "../../misc/templates/reference" ] @@ -40,7 +40,7 @@ let info = "root", "http://tpetricek.github.io/FSharp.FSharp.ProjectScaffold" ] [] -let ``MetadataFormat works on sample Deedle assembly``() = +let ``MetadataFormat works on sample Deedle assembly``() = let library = root @@ "files" @@ "Deedle.dll" let output = getOutputDir() MetadataFormat.Generate @@ -48,10 +48,10 @@ let ``MetadataFormat works on sample Deedle assembly``() = sourceRepo = "https://github.com/BlueMountainCapital/Deedle/tree/master/", sourceFolder = "c:/dev/FSharp.DataFrame") let files = Directory.GetFiles(output) - + let optIndex = files |> Seq.tryFind (fun s -> s.EndsWith "index.html") optIndex.IsSome |> shouldEqual true - + let optSeriesMod = files |> Seq.tryFind (fun s -> s.Contains "seriesmodule") optSeriesMod.IsSome |> shouldEqual true @@ -61,7 +61,7 @@ let ``MetadataFormat works on sample Deedle assembly``() = // Ignore by default to make tests run reasonably fast [] -let ``MetadataFormat works on sample FAKE assembly``() = +let ``MetadataFormat works on sample FAKE assembly``() = let library = root @@ "files" @@ "FAKE" @@ "FakeLib.dll" let output = getOutputDir() MetadataFormat.Generate(library, output, layoutRoots, info) @@ -106,7 +106,7 @@ let ``MetadataFormat works on two sample F# assemblies``() = files.["fslib-record.html"] |> should contain "Foo2()" files.["fslib-record.html"] |> should contain "Signature: unit -> int" files.["fslib-class.html"] |> should contain "new()" - files.["fslib-class.html"] |> should contain "Signature: unit -> Class" + files.["fslib-class.html"] |> should contain "Signature: unit -> Class" // Check that properties are correctly generated (#114) files.["fslib-class.html"] |> removeWhiteSpace |> should notContain ">Member(arg1)<" @@ -114,7 +114,7 @@ let ``MetadataFormat works on two sample F# assemblies``() = files.["fslib-class.html"] |> removeWhiteSpace |> should contain ">Member<" files.["fslib-class.html"] |> should notContain "Signature: unit -> int" files.["fslib-class.html"] |> should contain "Signature: int" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif @@ -139,7 +139,7 @@ let ``MetadataFormat generates Go to GitHub source links``() = files.["fslib-record.html"] |> should contain "https://github.com/tpetricek/FSharp.Formatting/tree/master/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library1.fs#L" files.["fslib-union.html"] |> should contain "github-link" files.["fslib-union.html"] |> should contain "https://github.com/tpetricek/FSharp.Formatting/tree/master/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library1.fs#L" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif @@ -249,22 +249,22 @@ let ``MetadataFormat test that csharp (publiconly) support works``() = files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Event" - - + + files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Method") files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Property") files.["csharpsupport-sampleclass.html"] |> should not' (contain "My_Private_Static_Event") files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Sample_Class" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Event" - + files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Method") files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Property") files.["csharpsupport-samplestaticclass.html"] |> should not' (contain "My_Private_Static_Event") - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif @@ -303,29 +303,29 @@ let ``MetadataFormat test that csharp support works``() = files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Static_Event" - - + + files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Method" files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Property" files.["csharpsupport-sampleclass.html"] |> should contain "My_Private_Static_Event" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Sample_Class" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Static_Event" - + files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Method" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Property" files.["csharpsupport-samplestaticclass.html"] |> should contain "My_Private_Static_Event" - + #if INTERACTIVE System.Diagnostics.Process.Start(output) #endif [] -let ``MetadataFormat process XML comments in two sample F# assemblies``() = - let libraries = +let ``MetadataFormat process XML comments in two sample F# assemblies``() = + let libraries = [ root @@ "files/TestLib/bin/Debug" @@ "TestLib1.dll" root @@ "files/TestLib/bin/Debug" @@ "TestLib2.dll" ] let output = getOutputDir() @@ -345,7 +345,7 @@ let ``MetadataFormat process XML comments in two sample F# assemblies``() = files.["fslib-nested-submodule.html"] |> should contain "Very nested field" [] -let ``MetadataFormat highlights code snippets in Markdown comments``() = +let ``MetadataFormat highlights code snippets in Markdown comments``() = let library = root @@ "files/TestLib/bin/Debug" @@ "TestLib1.dll" let output = getOutputDir() MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) @@ -362,7 +362,7 @@ let ``MetadataFormat handles c# dlls`` () = MetadataFormat.Generate ( library, output, layoutRoots, info, libDirs = [root @@ "../../lib"]) let files = Directory.GetFiles(output) - + let optIndex = files |> Seq.tryFind (fun s -> s.EndsWith "index.html") optIndex.IsSome |> shouldEqual true @@ -388,8 +388,8 @@ let ``MetadataFormat processes C# properties on types and includes xml comments MetadataFormat.Generate ( library, output, layoutRoots, info, libDirs = [root @@ "../../lib"]) let fileNames = Directory.GetFiles(output) - let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - + let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] + files.["manoli-utils-csharpformat-clikeformat.html"] |> should contain "CommentRegEx" files.["manoli-utils-csharpformat-clikeformat.html"] |> should contain "Regular expression string to match single line and multi-line" @@ -401,7 +401,7 @@ let ``MetadataFormat generates module link in nested types``() = MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [binDir; root @@ "../../lib"], markDownComments = true) let fileNames = Directory.GetFiles(output) let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - + // Check that the modules and type files have namespace information files.["fslib-class.html"] |> should contain "Namespace: FsLib" files.["fslib-nested.html"] |> should contain "Namespace: FsLib" @@ -450,20 +450,10 @@ let ``MetadataFormat test FsLib1``() = markDownComments = false) let fileNames = Directory.GetFiles(output) - // Check that a link to OtherType exists when using Logical Name of the type only let files = - - // Check that a link to a module is created when using Logical Name only dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - - // Check that a link to a type with a duplicated name is created when using full name - files.["fslib-nested-duplicatedtypename.html"] |> should contain "This type has the same name as FsLib.DuplicatedTypeName" - - // Check that a link to a type with a duplicated name is not created when using Logical name only files.ContainsKey "fslib-test_omit.html" |> should equal false - // Check that a link to a type with a duplicated name is not created when using Logical name only - files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." [] let ``Link to other types``() = let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" @@ -488,4 +478,4 @@ let ``Link to other types``() = files.["fslib-nested.html"] |> should contain "This function returns a [DuplicatedTypeName] multiplied by 4." // Check that a link to a type with a duplicated name is not created when using Logical name only - files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." + files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." \ No newline at end of file diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index 60c5e4215..e7f18d3c5 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -4,14 +4,14 @@ namespace FsLib type DuplicatedTypeName = int /// Sample class -type Class() = +type Class() = /// Readonly int property member x.Member = 0 /// Nested module -module Nested = +module Nested = /// Somewhat nested module - module Submodule = + module Submodule = /// Very nested field let supernested = 42 @@ -21,7 +21,7 @@ module Nested = member x.Member = "" /// Somewhat nested type - type NestedType() = + type NestedType() = /// Very nested member member x.Member = "" @@ -54,7 +54,7 @@ type Test_Issue229 (name) = interface ITest_Issue229 with /// interface comment - member x.Name = name + member x.Name = name type Test_Issue287 () = /// Function Foo! From 7f00aaa2ddc1866e5ef099a0ff7fd01cfd89bd44 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Thu, 8 Oct 2015 18:06:27 +0200 Subject: [PATCH 06/11] Added failing test. Collect InlineCode also. --- src/FSharp.MetadataFormat/Main.fs | 3 ++- tests/FSharp.MetadataFormat.Tests/Tests.fs | 6 +++++- tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index fb510c797..0192e787d 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -569,7 +569,8 @@ module Reader = /// Returns all indirect links in a specified span node let rec collectSpanIndirectLinks span = seq { match span with - | IndirectLink(_, _, key) -> yield key + | IndirectLink _ -> yield span + | InlineCode _ -> yield span | Matching.SpanLeaf _ -> () | Matching.SpanNode(_, spans) -> for s in spans do yield! collectSpanIndirectLinks s } diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index 53ee26bb0..aa53cccce 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -478,4 +478,8 @@ let ``Link to other types``() = files.["fslib-nested.html"] |> should contain "This function returns a [DuplicatedTypeName] multiplied by 4." // Check that a link to a type with a duplicated name is not created when using Logical name only - files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." \ No newline at end of file + files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." + + files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is" + + files.["fslib-nested.html"] \ No newline at end of file diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index e7f18d3c5..fe8a76565 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -35,6 +35,7 @@ module Nested = type DuplicatedTypeName = int /// This function returns a [FsLib.Nested.MyType] multiplied by 2. + /// You will notice that `FsLib.Nested.MyType` is just an `int` let f x :MyType = x * 2 /// This function returns a [OtherType] multiplied by 3. From 6592a176c919103fb71a4ad0ec3daa21eaddaafb Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Fri, 9 Oct 2015 16:39:24 +0200 Subject: [PATCH 07/11] Wrap inline code with linkable types inside IndirectLinks --- src/FSharp.MetadataFormat/Main.fs | 41 ++++++++++++++++------ tests/FSharp.MetadataFormat.Tests/Tests.fs | 9 +++-- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index 0192e787d..304bc8d08 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -569,8 +569,7 @@ module Reader = /// Returns all indirect links in a specified span node let rec collectSpanIndirectLinks span = seq { match span with - | IndirectLink _ -> yield span - | InlineCode _ -> yield span + | IndirectLink (_, _, key) -> yield key | Matching.SpanLeaf _ -> () | Matching.SpanNode(_, spans) -> for s in spans do yield! collectSpanIndirectLinks s } @@ -599,20 +598,40 @@ module Reader = | Some cRef -> if cRef.IsInternal then Some (undefinedLink, cRef) else None | None -> None - /// Ads a link to a Type to the document defined links + /// Adds a cross-type link to the document defined links let addLinkToType (doc: LiterateDocument) link = match link with - | Some(k, v) -> doc.DefinedLinks.Add(k, (v.ReferenceLink, Some v.NiceName)) |> ignore + | Some(k, v) -> do doc.DefinedLinks.Add(k, (v.ReferenceLink, Some v.NiceName)) | None -> () - /// Adds the missiing links to types to the document defined links + /// Wraps the span inside an `IndirectLink` if it is an inline code that can be converted to a link + let wrapInlineCodeLinksInSpans (ctx:ReadingContext) span = + match span with + | InlineCode(code) -> + match getTypeLink ctx code with + | Some _ -> IndirectLink([span], code, code) + | None -> span + | _ -> span + + /// Wraps inside an `IndirectLink` all inline code spans in the paragraph that can be converted to a link + let rec wrapInlineCodeLinksInParagraphs (ctx:ReadingContext) (para:MarkdownParagraph) = + match para with + | Matching.ParagraphLeaf _ -> para + | Matching.ParagraphNested(info, pars) -> + Matching.ParagraphNested(info, pars |> List.map (fun innerPars -> List.map (wrapInlineCodeLinksInParagraphs ctx) innerPars)) + | Matching.ParagraphSpans(info, spans) -> Matching.ParagraphSpans(info, List.map (wrapInlineCodeLinksInSpans ctx) spans) + + /// Adds the missing links to types to the document defined links let addMissingLinkToTypes ctx (doc: LiterateDocument) = - doc.Paragraphs - |> Seq.collect collectParagraphIndirectLinks - |> Seq.filter (linkNotDefined doc) - |> Seq.map (getTypeLink ctx) - |> Seq.iter (addLinkToType doc) - doc + let replacedParagraphs = doc.Paragraphs |> List.map (wrapInlineCodeLinksInParagraphs ctx) + + do replacedParagraphs + |> Seq.collect collectParagraphIndirectLinks + |> Seq.filter (linkNotDefined doc) + |> Seq.map (getTypeLink ctx) + |> Seq.iter (addLinkToType doc) + + LiterateDocument(replacedParagraphs, doc.FormattedTips, doc.DefinedLinks, doc.Source, doc.SourceFile, doc.Errors) let readCommentAndCommands (ctx:ReadingContext) xmlSig = match ctx.XmlMemberLookup(xmlSig) with diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index aa53cccce..cab042f6b 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -455,13 +455,15 @@ let ``MetadataFormat test FsLib1``() = files.ContainsKey "fslib-test_omit.html" |> should equal false [] -let ``Link to other types``() = +let ``Metadata generates cross-type links``() = let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" let output = getOutputDir() MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) let fileNames = Directory.GetFiles(output) let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] + // -------------------Indirect links---------------------------------- + // Check that a link to MyType exists when using Full Name of the type files.["fslib-nested.html"] |> should contain "This function returns a FsLib.Nested.MyType" @@ -480,6 +482,7 @@ let ``Link to other types``() = // Check that a link to a type with a duplicated name is not created when using Logical name only files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." - files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is" + // -------------------Inline code---------------------------------- - files.["fslib-nested.html"] \ No newline at end of file + // Check that a link to MyType exists when using Full Name of the type in a inline code + files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is" \ No newline at end of file From edcbe7f3cf5e86f6aff568a10a57dd07d5b26a92 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Fri, 9 Oct 2015 16:52:44 +0200 Subject: [PATCH 08/11] Add more tests for wrapping inline code with links --- tests/FSharp.MetadataFormat.Tests/Tests.fs | 17 ++++++++++++++++- .../files/FsLib/Library2.fs | 5 +++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index cab042f6b..be7c76d09 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -485,4 +485,19 @@ let ``Metadata generates cross-type links``() = // -------------------Inline code---------------------------------- // Check that a link to MyType exists when using Full Name of the type in a inline code - files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is" \ No newline at end of file + files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is just an int" + + // Check that a link to MyType exists when using Full Name of the type in a inline code + files.["fslib-nested.html"] |> should contain "You will notice that OtherType is just an int" + + // Check that a link to a type with a duplicated name is not created when using Logical name only + files.["fslib-nested.html"] |> should contain "DuplicatedTypeName is duplicated so it should no add a cross-type link" + + // Check that a link to a type with a duplicated name is not created when using Logical name only + files.["fslib-nested.html"] |> should contain "InexistentTypeName does not exists so it should no add a cross-type link" + + // Check that a link to a module is created when using Logical Name only + files.["fslib-duplicatedtypename.html"] |> should contain "This type name will be duplicated in Nested" + + // Check that a link to a type with a duplicated name is created when using full name + files.["fslib-nested-duplicatedtypename.html"] |> should contain "This type has the same name as FsLib.DuplicatedTypeName" \ No newline at end of file diff --git a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs index fe8a76565..f83dd9b58 100644 --- a/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs +++ b/tests/FSharp.MetadataFormat.Tests/files/FsLib/Library2.fs @@ -1,6 +1,7 @@ namespace FsLib /// This type name will be duplicated in [Nested] +/// This type name will be duplicated in `Nested` type DuplicatedTypeName = int /// Sample class @@ -32,6 +33,7 @@ module Nested = type OtherType = int /// This type has the same name as [FsLib.DuplicatedTypeName] + /// This type has the same name as `FsLib.DuplicatedTypeName` type DuplicatedTypeName = int /// This function returns a [FsLib.Nested.MyType] multiplied by 2. @@ -39,12 +41,15 @@ module Nested = let f x :MyType = x * 2 /// This function returns a [OtherType] multiplied by 3. + /// You will notice that `OtherType` is just an `int` let f2 x :OtherType = x * 3 /// This function returns a [DuplicatedTypeName] multiplied by 4. + /// `DuplicatedTypeName` is duplicated so it should no add a cross-type link let f3 x :OtherType = x * 4 /// This function returns a [InexistentTypeName] multiplied by 5. + /// `InexistentTypeName` does not exists so it should no add a cross-type link let f4 x :OtherType = x * 5 type ITest_Issue229 = abstract member Name : string From df69df556a26da96f3cc81f0b42b459ea68c0956 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Wed, 14 Oct 2015 17:13:14 +0200 Subject: [PATCH 09/11] Separate test and give better names --- tests/FSharp.MetadataFormat.Tests/Tests.fs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.MetadataFormat.Tests/Tests.fs b/tests/FSharp.MetadataFormat.Tests/Tests.fs index be7c76d09..0213a895f 100644 --- a/tests/FSharp.MetadataFormat.Tests/Tests.fs +++ b/tests/FSharp.MetadataFormat.Tests/Tests.fs @@ -454,16 +454,15 @@ let ``MetadataFormat test FsLib1``() = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] files.ContainsKey "fslib-test_omit.html" |> should equal false +// -------------------Indirect links---------------------------------- [] -let ``Metadata generates cross-type links``() = +let ``Metadata generates cross-type links for Indirect Links``() = let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" let output = getOutputDir() MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) let fileNames = Directory.GetFiles(output) let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] - // -------------------Indirect links---------------------------------- - // Check that a link to MyType exists when using Full Name of the type files.["fslib-nested.html"] |> should contain "This function returns a FsLib.Nested.MyType" @@ -483,6 +482,12 @@ let ``Metadata generates cross-type links``() = files.["fslib-nested.html"] |> should contain "This function returns a [InexistentTypeName] multiplied by 5." // -------------------Inline code---------------------------------- +let ``Metadata generates cross-type links for Inline Code``() = + let library = root @@ "files/FsLib/bin/Debug" @@ "FsLib2.dll" + let output = getOutputDir() + MetadataFormat.Generate([library], output, layoutRoots, info, libDirs = [root @@ "../../lib"], markDownComments = true) + let fileNames = Directory.GetFiles(output) + let files = dict [ for f in fileNames -> Path.GetFileName(f), File.ReadAllText(f) ] // Check that a link to MyType exists when using Full Name of the type in a inline code files.["fslib-nested.html"] |> should contain "You will notice that FsLib.Nested.MyType is just an int" From e57d953eabd97127cac84686a30d08f866a2d92c Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Wed, 14 Oct 2015 17:16:56 +0200 Subject: [PATCH 10/11] Add warning when duplicated types were found for a simple name --- src/FSharp.MetadataFormat/Main.fs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FSharp.MetadataFormat/Main.fs b/src/FSharp.MetadataFormat/Main.fs index 304bc8d08..38a27c189 100644 --- a/src/FSharp.MetadataFormat/Main.fs +++ b/src/FSharp.MetadataFormat/Main.fs @@ -813,7 +813,12 @@ module Reader = | _ -> match niceNameEntityLookup.TryGetValue(typeName) with | true, entityList -> - if entityList.Count = 1 then Some{ IsInternal = true; ReferenceLink = sprintf "%s.html" (getUrl entityList.[0]); NiceName = entityList.[0].LogicalName } else None + if entityList.Count = 1 then + Some{ IsInternal = true; ReferenceLink = sprintf "%s.html" (getUrl entityList.[0]); NiceName = entityList.[0].LogicalName } + else + if entityList.Count > 1 then + do Log.warnf "Duplicate types found for the simple name: %s" typeName + None | _ -> None let resolveCref (cref:string) = From 8e18caa77a56337f4b18073dce52b10d2fb3c373 Mon Sep 17 00:00:00 2001 From: Limo Wan Kenobi Date: Wed, 14 Oct 2015 17:22:31 +0200 Subject: [PATCH 11/11] Added documentation for cross-type links in metadata docs --- docs/content/metadata.fsx | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/content/metadata.fsx b/docs/content/metadata.fsx index cee8c33a3..9ef3ec7f7 100644 --- a/docs/content/metadata.fsx +++ b/docs/content/metadata.fsx @@ -52,6 +52,55 @@ MetadataFormat.Generate sourceRepo = "https://github.com/tpetricek/FSharp.Formatting/tree/master", sourceFolder = "/path/to/FSharp.Formatting" ) + +(** +Adding cross-type links to modules and types in the same assembly +----------------- +You can automatically add cross-type links to the documentation pages of other modules and types in the same assembly. +You can do this in two different ways: +* Add a [markdown inline link](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#links) were the link +title is the name of the type you want to link. + + + /// this will generate a link to [Foo.Bar] documentation + + +* Add a [Markdown inlide code](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) (using +back-ticks) where the code is the name of the type you want to link. + + + /// This will also generate a link to `Foo.Bar` documentation + + +You can use either the full name (including namespace and module) or the simple name of a type. +If more than one type is found with the same name the link will not be generated. +If a type with the given name is not found in the same assembly the link will not be generated. +*) + +/// Contains two types [Bar] and [Foo.Baz] +module Foo = + + /// Bar is just an `int` and belongs to module [Foo] + type Bar = int + + /// Baz contains a `Foo.Bar` as its `id` + type Baz = { id: Bar } + + /// This function operates on `Baz` types. + let f (b:Baz) = + b.id * 42 + +/// Referencing [Foo3] will not generate a link as there is no type with the name `Foo3` +module Foo2 = + + /// This is not the same type as `Foo.Bar` + type Bar = double + + /// Using the simple name for [Bar] will fail to create a link because the name is duplicated in + /// [Foo.Bar] and in [Foo2.Bar]. In this case, using the full name works. + let f2 b = + b * 50 + (** Excluding APIs from the docs -----------------