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

One extension members shows four times in docs. #941

Open
goswinr opened this issue Nov 1, 2024 · 3 comments
Open

One extension members shows four times in docs. #941

goswinr opened this issue Nov 1, 2024 · 3 comments

Comments

@goswinr
Copy link
Contributor

goswinr commented Nov 1, 2024

I made an extension member called .Last with get and set for 'T[].
It shows up four times in the generated docs. Can I fix this somehow ?
image
https://goswinr.github.io/ArrayT/reference/arrayt-autoopenarraytextensions.html

@nojaf
Copy link
Collaborator

nojaf commented Nov 2, 2024

I can somewhat understand why this happend.

image

The with get and set syntax is sugar for a mutable field, a get binding and a set binding.
It might have another symbol for the property which makes it appear four times.

I would accept a PR to fix this, but I wonder if we have a special case for a property to begin with.

@goswinr
Copy link
Contributor Author

goswinr commented Nov 2, 2024

Thanks Florian, I thought so too, I am not familiar with the codebase, can you give me a hint where to get started for such a PR?

@nojaf
Copy link
Collaborator

nojaf commented Nov 2, 2024

I'm less familiar with that part of the codebase, but I would peek at

static member internal Generate
(
projects: ApiDocInput list,
collectionName,
libDirs,
otherFlags,
qualify,
urlRangeHighlight,
root,
substitutions,
onError,
extensions
) =
// Default template file names
let otherFlags = defaultArg otherFlags [] |> List.map (fun (o: string) -> o.Trim())
let libDirs = defaultArg libDirs [] |> List.map Path.GetFullPath
let dllFiles = projects |> List.map (fun p -> Path.GetFullPath p.Path)
let urlRangeHighlight =
defaultArg urlRangeHighlight (fun url start stop -> String.Format("{0}#L{1}-{2}", url, start, stop))
// Compiler arguments used when formatting code snippets inside Markdown comments
let codeFormatCompilerArgs =
[ for dir in libDirs do
yield sprintf "-I:\"%s\"" dir
for file in dllFiles do
yield sprintf "-r:\"%s\"" file ]
|> String.concat " "
printfn " loading %d assemblies..." dllFiles.Length
let resolvedList =
FSharpAssembly.LoadFiles(dllFiles, libDirs, otherFlags = otherFlags)
|> List.zip projects
// generate the names for the html files beforehand so we can resolve <see cref=""/> links.
let urlMap = CrossReferenceResolver(root, collectionName, qualify, extensions)
// Read and process assemblies and the corresponding XML files
let assemblies =
for (_, asmOpt) in resolvedList do
match asmOpt with
| (_, Some asm) ->
printfn " registering entities for assembly %s..." asm.SimpleName
asm.Contents.Entities |> Seq.iter (urlMap.RegisterEntity)
| _ -> ()
resolvedList
|> List.choose (fun (project, (dllFile, asmOpt)) ->
let sourceFolderRepo =
match project.SourceFolder, project.SourceRepo with
| Some folder, Some repo -> Some(folder, repo)
| Some _folder, _ ->
Log.warnf "Repository url should be specified along with source folder."
None
| _, Some _repo ->
Log.warnf "Repository url should be specified along with source folder."
None
| _ -> None
match asmOpt with
| None ->
printfn "**** Skipping assembly '%s' because was not found in resolved assembly list" dllFile
onError "exiting"
None
| Some asm ->
printfn " reading XML doc for %s..." dllFile
let xmlFile = defaultArg project.XmlFile (Path.ChangeExtension(dllFile, ".xml"))
let xmlFileNoExt = Path.GetFileNameWithoutExtension(xmlFile)
let xmlFileOpt =
//Directory.EnumerateFiles(Path.GetDirectoryName(xmlFile), xmlFileNoExt + ".*")
Directory.EnumerateFiles(Path.GetDirectoryName xmlFile)
|> Seq.filter (fun file ->
let fileNoExt = Path.GetFileNameWithoutExtension file
let ext = Path.GetExtension file
xmlFileNoExt.Equals(fileNoExt, StringComparison.OrdinalIgnoreCase)
&& ext.Equals(".xml", StringComparison.OrdinalIgnoreCase))
|> Seq.tryHead
//|> Seq.map (fun f -> f, f.Remove(0, xmlFile.Length - 4))
//|> Seq.tryPick (fun (f, ext) ->
// if ext.Equals(".xml", StringComparison.CurrentCultureIgnoreCase)
// then Some(f) else None)
let publicOnly = project.PublicOnly
let mdcomments = project.MarkdownComments
let substitutions = defaultArg project.Substitutions substitutions
match xmlFileOpt with
| None -> raise (FileNotFoundException(sprintf "Associated XML file '%s' was not found." xmlFile))
| Some xmlFile ->
printfn " reading assembly data for %s..." dllFile
SymbolReader.readAssembly (
asm,
publicOnly,
xmlFile,
substitutions,
sourceFolderRepo,
urlRangeHighlight,
mdcomments,
urlMap,
codeFormatCompilerArgs,
project.Warn
)
|> Some)
printfn " collecting namespaces..."
// Union namespaces from multiple libraries
let namespaces = Dictionary<_, (_ * _ * Substitutions)>()
for asm, nss in assemblies do
for ns in nss do
printfn " found namespace %s in assembly %s..." ns.Name asm.Name
match namespaces.TryGetValue(ns.Name) with
| true, (entities, summary, substitutions) ->
namespaces.[ns.Name] <-
(entities @ ns.Entities, combineNamespaceDocs [ ns.NamespaceDocs; summary ], substitutions)
| false, _ -> namespaces.Add(ns.Name, (ns.Entities, ns.NamespaceDocs, ns.Substitutions))
let namespaces =
[ for (KeyValue(name, (entities, summary, substitutions))) in namespaces do
printfn " found %d entities in namespace %s..." entities.Length name
if entities.Length > 0 then
ApiDocNamespace(name, entities, substitutions, summary) ]
printfn " found %d namespaces..." namespaces.Length
let collection =
ApiDocCollection(collectionName, List.map fst assemblies, namespaces |> List.sortBy (fun ns -> ns.Name))
let rec nestedModules ns parent (modul: ApiDocEntity) =
[ yield ApiDocEntityInfo(modul, collection, ns, parent)
for n in modul.NestedEntities do
if not n.IsTypeDefinition then
yield! nestedModules ns (Some modul) n ]
let moduleInfos =
[ for ns in collection.Namespaces do
for n in ns.Entities do
if not n.IsTypeDefinition then
yield! nestedModules ns None n ]
let createType ns parent typ =
ApiDocEntityInfo(typ, collection, ns, parent)
let rec nestedTypes ns (modul: ApiDocEntity) =
[ let entities = modul.NestedEntities
for n in entities do
if n.IsTypeDefinition then
yield createType ns (Some modul) n
for n in entities do
if not n.IsTypeDefinition then
yield! nestedTypes ns n ]
let typesInfos =
[ for ns in collection.Namespaces do
let entities = ns.Entities
for n in entities do
if not n.IsTypeDefinition then
yield! nestedTypes ns n
for n in entities do
if n.IsTypeDefinition then
yield createType ns None n ]
ApiDocModel(
substitutions = substitutions,
collection = collection,
entityInfos = moduleInfos @ typesInfos,
root = root,
qualify = qualify,
fileExtensions = extensions,
urlMap = urlMap
)

You can probably play with https://fsprojects.github.io/FSharp.Formatting/apidocs.html#Building-library-documentation-programmatically to investigate what happens under the hood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants