View mode: basic / threaded / horizontal-split · Log in · Help
October 15, 2010
automatic code examples in documentation
This is a post i made deep in the 'improving the join function' thread.
Steven asked me to open a new thread on it, so here it comes.


Am 13.10.2010 22:07, schrieb Andrei Alexandrescu:

> >
> > Good point. On the other hand, an overly simplified documentation
> > might hinder a good deal of legit uses for advanced users. I wonder
> > how to please everyone.
>   
I think the best way to explain the usage of a feature are *working* code-examples.
Maybe it's possible to have a special unit-test block named such as 'example'.
The compiler can completely ignore such sections or just syntax check them, or ... .

For doc generation they are just taken as they are and put into (or linked to) the documentation.

It may be even possible for the doc generator to compile and run these samples, so they become some kind of unit test and their possible output
can be part of the documentation.

Just an idea that comes to my mind



This was the original post, now some more explanation:

How can the syntax look like ?


... library code

@documentation( code) {
 //hello world example code
 import std.stdio;
 void main() {
    writeln( "Hello, world!");	
 }
}

more library code ...

This is how a simple example code section may look like.
The @documentation annotation tells the compiler not to generate any code
from the section. The minimal thing it has to do is generate a string from
the section content and forward it to the document-generator.
This should be sufficient for easily getting code examples into the documentation.

I think its a good idea if the compiler executes a syntax check on the example section,
like it does on the already implemented syntax checked strings.

Then the compiler part is done with this. This are code examples, not unit tests.
They are not run with the other unit tests. 
I think code examples are most usefull if they are self-contained little programs.

Part of the document generation may be to compile and run the extracted examples.
When a example does't compile it can be marked as defunct or excluded from the 
documentation. The doc-generator can catch the output of the running examples 
and add it to the documentation as result.

Shurely there are some problems when trying to compile the examples like wich 
libs to link with, or what about GUI-code, or just code snippets, but for me 
this is all secondary, maybe we can make that work later. The most important part 
is to define the transfer mechanics to get the example code into the documentation.

So what do you think?


Gerrit
October 15, 2010
Re: automatic code examples in documentation
On 10/15/2010 10:18 AM, Gerrit Wichert wrote:
> This is a post i made deep in the 'improving the join function' thread.
> Steven asked me to open a new thread on it, so here it comes.
>
>
> Am 13.10.2010 22:07, schrieb Andrei Alexandrescu:
>
>> >
>> >  Good point. On the other hand, an overly simplified documentation
>> >  might hinder a good deal of legit uses for advanced users. I wonder
>> >  how to please everyone.
>>
> I think the best way to explain the usage of a feature are*working*  code-examples.
> Maybe it's possible to have a special unit-test block named such as 'example'.
> The compiler can completely ignore such sections or just syntax check them, or ... .
>
> For doc generation they are just taken as they are and put into (or linked to) the documentation.
>
> It may be even possible for the doc generator to compile and run these samples, so they become some kind of unit test and their possible output
> can be part of the documentation.
>
> Just an idea that comes to my mind
>
>
>
> This was the original post, now some more explanation:
>
> How can the syntax look like ?
>
>
> ... library code
>
> @documentation( code) {
>    //hello world example code
>    import std.stdio;
>    void main() {
>       writeln( "Hello, world!");	
>    }
> }
>
> more library code ...
[snip]

> So what do you think?

I'm happy with a much more modest change that doesn't add anything to 
the syntax. Simply prefixing a unittest with a documentation comment 
makes it an example:

/**
The example below illustrates how D gets a basic arithmetic operation 
totally right.
*/
unittest
{
    assert(1 + 1 == 2);
}

The documentation generator simply plops the comment and then formats 
the code as an example code.


Andrei
October 15, 2010
Re: automatic code examples in documentation
Andrei Alexandrescu wrote:

> On 10/15/2010 10:18 AM, Gerrit Wichert wrote:
>> This is a post i made deep in the 'improving the join function' thread.
>> Steven asked me to open a new thread on it, so here it comes.
>>
>>
>> Am 13.10.2010 22:07, schrieb Andrei Alexandrescu:
>>
>>> >
>>> >  Good point. On the other hand, an overly simplified documentation
>>> >  might hinder a good deal of legit uses for advanced users. I wonder
>>> >  how to please everyone.
>>>
>> I think the best way to explain the usage of a feature are*working* 
>> code-examples. Maybe it's possible to have a special unit-test block
>> named such as 'example'. The compiler can completely ignore such
>> sections or just syntax check them, or ... .
>>
>> For doc generation they are just taken as they are and put into (or
>> linked to) the documentation.
>>
>> It may be even possible for the doc generator to compile and run these
>> samples, so they become some kind of unit test and their possible output
>> can be part of the documentation.
>>
>> Just an idea that comes to my mind
>>
>>
>>
>> This was the original post, now some more explanation:
>>
>> How can the syntax look like ?
>>
>>
>> ... library code
>>
>> @documentation( code) {
>>    //hello world example code
>>    import std.stdio;
>>    void main() {
>>       writeln( "Hello, world!");
>>    }
>> }
>>
>> more library code ...
> [snip]
> 
>> So what do you think?
> 
> I'm happy with a much more modest change that doesn't add anything to
> the syntax. Simply prefixing a unittest with a documentation comment
> makes it an example:
> 
> /**
> The example below illustrates how D gets a basic arithmetic operation
> totally right.
> */
> unittest
> {
>      assert(1 + 1 == 2);
> }
> 
> The documentation generator simply plops the comment and then formats
> the code as an example code.
> 
> 
> Andrei

for reference: http://d.puremagic.com/issues/show_bug.cgi?id=2630

Tomasz Sowiński raises the point that each unittest should test the 
preceding declaration. I think that's a little inflexible, instead the 
following could work:

- unittests marked with 'ditto' will document the preceding declaration
- unittest not marked with ditto will be put in a hardwired macro like BODY 
is, so that you have control where it gets put in the generated 
documentation.
October 15, 2010
Re: automatic code examples in documentation
Lutger napisał:

> for reference: http://d.puremagic.com/issues/show_bug.cgi?id=2630
> 
> Tomasz Sowiński raises the point that each unittest should test the
> preceding declaration. I think that's a little inflexible, instead the
> following could work:
> 
> - unittests marked with 'ditto' will document the preceding declaration

Well, a unittest making a trial run of the preceding declaration is a convention, natural and 
widely adopted. That well-trodden path deserves to be acknowledged by the doc generator.

Good thing about this idea is that *nothing* changes, no extra gimmicks around unittest 
blocks, the code's natural flow is intact.

> - unittest not marked with ditto will be put in a hardwired macro like
> BODY is, so that you have control where it gets put in the generated
> documentation.

Hm.. would the hardwired macro name be same for all unittests? If so, the notion of implicit 
ownership by the preceding declaration is necessary so that the names wouldn't mix up.

-- 
Tomek
October 15, 2010
Re: automatic code examples in documentation
Andrei Alexandrescu napisał:

> I'm happy with a much more modest change that doesn't add anything to
> the syntax. Simply prefixing a unittest with a documentation comment
> makes it an example:
> 
> /**
> The example below illustrates how D gets a basic arithmetic operation
> totally right.
> */
> unittest
> {
> assert(1 + 1 == 2);
> }
> 
> The documentation generator simply plops the comment and then formats
> the code as an example code.

Let's drill down on this:

/// The ultimate foo.
void foo();

/// The test.
unittest { ... }

What would be the <dl><dt><dd> outline of the above snippet?

-- 
Tomek
October 15, 2010
Re: automatic code examples in documentation
On 10/15/10 18:00 CDT, Tomek Sowiński wrote:
> Andrei Alexandrescu napisał:
>
>> I'm happy with a much more modest change that doesn't add anything to
>> the syntax. Simply prefixing a unittest with a documentation comment
>> makes it an example:
>>
>> /**
>> The example below illustrates how D gets a basic arithmetic operation
>> totally right.
>> */
>> unittest
>> {
>> assert(1 + 1 == 2);
>> }
>>
>> The documentation generator simply plops the comment and then formats
>> the code as an example code.
>
> Let's drill down on this:
>
> /// The ultimate foo.
> void foo();
>
> /// The test.
> unittest { ... }
>
> What would be the<dl><dt><dd>  outline of the above snippet?

From a ddoc perspective this should be the same as:

/** The ultimate foo.

The test.
----
...
----
*/
void foo();


Andrei
October 15, 2010
Re: automatic code examples in documentation
Andrei Alexandrescu napisał:

>> Let's drill down on this:
>>
>> /// The ultimate foo.
>> void foo();
>>
>> /// The test.
>> unittest { ... }
>>
>> What would be the<dl><dt><dd>  outline of the above snippet?
> 
> From a ddoc perspective this should be the same as:
> 
> /** The ultimate foo.
> 
> The test.
> ----
> ...
> ----
> */
> void foo();

I see. That means unittests summarizing the whole of module's goodies would have to be 
at the top, but that's passable. Otherwise it's a superb idea.

As I mentioned in bugzilla, it opens the opportunity to kill the unittest naming problem with 
the same stone:

void foo();

unittest(owner) {
 Log.info("Testing " ~ owner.stringof ~ "...");
 scope(exit) Log.info("Testing " ~ owner.stringof ~ " complete");
}

The syntax takes after the out(result) contract. 'owner' is an alias to the preceding symbol. 
The overall ROI looks positive, eh?

-- 
Tomek
October 16, 2010
Re: automatic code examples in documentation
Tomek Sowiński napisał:

> As I mentioned in bugzilla, it opens the opportunity to kill the unittest
> naming problem with the same stone:
> 
> void foo();
> 
> unittest(owner) {
> Log.info("Testing " ~ owner.stringof ~ "...");
> scope(exit) Log.info("Testing " ~ owner.stringof ~ " complete");
> }
> 
> The syntax takes after the out(result) contract. 'owner' is an alias to
> the preceding symbol. The overall ROI looks positive, eh?

Nevermind. It's little better than:

unittest {
 alias foo owner;
 Log.info("Testing " ~ owner.stringof ~ "...");
 scope(exit) Log.info("Testing " ~ owner.stringof ~ " complete");
}

There must be a way to make it all work elegantly with, say, an IDE's unittest runner, but I 
won't find it posting at 2:28 a.m.

-- 
Tomek
October 16, 2010
Re: automatic code examples in documentation
On Friday, October 15, 2010 16:49:06 Tomek Sowiński wrote:
> Andrei Alexandrescu napisał:
> >> Let's drill down on this:
> >> 
> >> /// The ultimate foo.
> >> void foo();
> >> 
> >> /// The test.
> >> unittest { ... }
> >> 
> >> What would be the<dl><dt><dd>  outline of the above snippet?
> > 
> > From a ddoc perspective this should be the same as:
> > 
> > /** The ultimate foo.
> > 
> > The test.
> > ----
> > ...
> > ----
> > */
> > void foo();
> 
> I see. That means unittests summarizing the whole of module's goodies would
> have to be at the top, but that's passable. Otherwise it's a superb idea.
> 
> As I mentioned in bugzilla, it opens the opportunity to kill the unittest
> naming problem with the same stone:
> 
> void foo();
> 
> unittest(owner) {
>   Log.info("Testing " ~ owner.stringof ~ "...");
>   scope(exit) Log.info("Testing " ~ owner.stringof ~ " complete");
> }
> 
> The syntax takes after the out(result) contract. 'owner' is an alias to the
> preceding symbol. The overall ROI looks positive, eh?

I'd actually consider that to be a bad idea.

1. We should be able to name unit tests independently of any function or 
functions that they're testing.

2. It should be fully possible to have more than one unit test for a single 
function or have one unit test for multiple functions and have names on those 
unittest blocks.

Only a small portion of unit test code necessarily makes sense as an example. 
So, while having syntax that indicates that a test goes with a particular 
function as its example is a good idea, remember that there are going to be 
plenty of other unittest blocks that are _not_ intended as examples. I'm not 
sure that we want to mix up named unit tests and unit tests which become 
examples in ddoc comments.

I fully support the syntax of

unittest(testname)
{
}

but I don't like the idea of

unittest(owner)
{
}

I think that it would make far more sense to do it in another way, perhaps

@example
unittest
{
}

or to have an example unit test with a name

@example
unittest(testname)
{
}

Or we could simple use a ddoc marker on it as Andrei suggested:

///
unittest(testname)
{
}

The one issue is templates. Putting a unittest in a block in a template doesn't 
make much sense for examples. For an example, you'd need to be dealing with a 
concrete template instantiation, while a unittest block within a template type 
would be for all instantiations of that template. So, in that case, being able 
to indicate an owner would certainly be useful. But I'm loathe to do it in away 
that makes it harder to add proper unit test names. Maybe what we do is make it 
so that unit test names which match a function name within that module are 
associated with that function as its example and the test function is given the 
same name as the function with _example tacked on or something similar. So,

void func() {}

unittest(mytest)
{
}

unittest(func)
{
}

would result in a named unit test mytest which was not an example, and a named 
unit test func_example which was the example for func() and was put in its ddoc.

- Jonathan M Davis
October 16, 2010
Re: automatic code examples in documentation
Tomek Sowiński wrote:

> Lutger napisał:
> 
>> for reference: http://d.puremagic.com/issues/show_bug.cgi?id=2630
>> 
>> Tomasz Sowiński raises the point that each unittest should test the
>> preceding declaration. I think that's a little inflexible, instead the
>> following could work:
>> 
>> - unittests marked with 'ditto' will document the preceding declaration
> 
> Well, a unittest making a trial run of the preceding declaration is a
> convention, natural and widely adopted. That well-trodden path deserves
> to be acknowledged by the doc generator.

That's why I suggested ditto. Any comments can be put as regular code 
comments inside the unittest itself, that will be marked up nicely by ddoc.

> Good thing about this idea is that *nothing* changes, no extra gimmicks
> around unittest blocks, the code's natural flow is intact.
> 
>> - unittest not marked with ditto will be put in a hardwired macro like
>> BODY is, so that you have control where it gets put in the generated
>> documentation.
> 
> Hm.. would the hardwired macro name be same for all unittests? If so, the
> notion of implicit ownership by the preceding declaration is necessary so
> that the names wouldn't mix up.
>

Not necessarily. It could just be a container.

With this macro:

DDOC_UNITTEST_MEMBERS = <h2>unittests</h2> $0

/** one plus one*/
unittest { assert(1+1==2); }

/** one minus one */
unittest { assert(1-1==0); }

the above could expand to something like: 

<h2>unittests</h2>
$(DDOC_SUMMARY one plus one)
$(D_CODE unittest { assert(1+1==2); } )
$(DDOC_SUMMARY one minus one)
$(D_CODE unittest { assert(1-1==0); } )
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home