Documenting F# Code
Asked Answered
H

4

27

In a C# class with a single constructor, I can add class summary XML documentation and constructor XML documentation:

///<summary>
///This class will solve all your problems
///</summary>
public class Awesome
{
    /// <summary>
    /// Initializes a new instance of the <see cref="Awesome"/> class.
    /// </summary>
    /// <param name="sauce">The secret sauce.</param>       
    public Awesome(string sauce)
    {
        //...implementation elided for security purposes
    }
}

How do I do the same with the equivalent F# class such that the generated documentation is the same?

type Awesome(sauce: string) = 
    //...implementation elided for security purposes

CLARIFICATION: I'm aware that the standard XML documentation tags can be used in F#. My question is how to add them to the above snippet so that both the type and the constructor are documented.

Hydrozoan answered 27/2, 2013 at 20:33 Comment(1)
+1 Good catch. I don't think there is a way to do this :-(Towhaired
T
19

I looked at the source of the open-source F# compiler and I think Dr_Asik is right - there is no way of documenting the implicit constructor with an XML comment. The node that represents the implicit constructor in the AST (See ImplicitCtor in ast.fs here) does not include a field for stroing the XML documentation (represented as PreXmlDoc type).

You can still document all public API - you'd have to use the method that Dr_Asik mentioned and mark the implicit constructor as private. I agree this is a bit ugly, but I think it is more convenient than not using implicit constructors:

type MyType private(a:int, u:unit) =
  /// <summary>Creates MyType</summary>
  /// <param name="a">Parameter A</param>
  new(a:int) = MyType(a, ())

I added a dummy parameter u to the implicit constructor, so that it can be called from the public constructor. Anyway, I think this should be considered as a language bug and so I'd suggest reporting this to fsbugs at microsoft dot com.

As an aside, I think the XML documentation is mainly useful as a source of data for IntelliSense (which still needs documentation for the constructor, though) and I created some alternative F# tools that let you create tutorials and documentation by writing an F# script file with special comments using Markdown (there is a blog post about it) - so you may consider that as a useful addition to the standard XML tooling.

Towhaired answered 28/2, 2013 at 2:12 Comment(3)
Thanks, this is my preferred workaround, though I agree it is a language bug. I've filed a report.Hydrozoan
Hey Tomas, I tried this approach, and while it does add the Intellisense to the constructor itself, I am not able to see the Intellisense on the standalone fields. Do you have any ideas on it? I was thinking of trying to hack a VS extension to help with some of the intellisense completeness that I sorely miss from C#.Cinque
This no longer appears to be the case. According to the docs, you can now add XML doc comments after the class name and before the implicit constructor argument list.. learn.microsoft.com/en-us/dotnet/fsharp/language-reference/…Loveinidleness
H
14

In exactly the same way as you do in C#: http://msdn.microsoft.com/en-us/library/dd233217.aspx

If you don't put any tags, F# assumes it is "summary":

/// This is the documentation
type MyType() = ....

... is equivalent to

/// <summary>This is the documentation</summary>
type MyType() = ...

If you want to document a constructor, you'll have to declare it explicitely. AFAIK there is no way to document the primary constructor.

/// [Type summary goes here]
type MyType(a : int) =
    let m_a = a
    /// [Parameterless constructor documentation here]
    new() = MyType(0)
Hendley answered 27/2, 2013 at 20:37 Comment(1)
Sorry, I should have been clearer in my question, which was only about how to document both the type summary and the primary constructor. It seems crazy that there is no way to document the primary constructor - that implies no-one can document their F# APIs using the standard tools.Hydrozoan
N
9

There is no way to document the implicit constructor with an XML comment inside an F# source file (.fs). One workaround is to declare the constructor explicitly (see Dr Asik's answer). Another is to put your XML comments into an F# Signature File (.fsi).

File.fs:

module File

type Awesome(sauce: string) =
    member x.Sauce = sauce

File.fsi

module File

type Awesome =
  class
    /// Implicit constructor summary for the Awesome type
    new : sauce:string -> Awesome
    member Sauce : string
  end

The XML documentation for this assembly will now contain the correct summary:

<member name="M:File.Awesome.#ctor(System.String)">
<summary>
 Implicit constructor summary for the Awesome type
</summary>
</member>
Nollie answered 28/2, 2013 at 14:55 Comment(1)
Thanks, that's an interesting option. I was vaguely aware of fsi files, but hadn't investigated them properly. However, for ease of use I prefer Tomas' suggestion.Hydrozoan
E
4

This really is an annoying problem. Another solution I ended up using is to not rely on a primary constructor:

/// Documentation type.
type Awesome =
    val sauce : string
    /// <summary>Documentation constructor.</summary>
    /// <param name="sauce">Sauce. Lots of it.</param>
    new (sauce) = { sauce = sauce }

More verbose, but no extra files or private constructors needed...

Enwrap answered 5/8, 2013 at 14:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.