-
Notifications
You must be signed in to change notification settings - Fork 256
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
Feat: Documenting Dafny Entities (Adding Docstring) #3756
Conversation
Source/DafnyCore/AST/MemberDecls.cs
Outdated
return EndToken.TrailingTrivia; | ||
} | ||
|
||
return GetTriviaContainingDocstringFromStartTokeOrNull(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return GetTriviaContainingDocstringFromStartTokeOrNull(); | |
return GetTriviaContainingDocstringFromStartTokenOrNull(); |
And anywhere else this name is used
Source/DafnyCore/Generic/Node.cs
Outdated
var match = matches[i]; | ||
if (match.Groups["multiline"].Success) { | ||
// For each line except the first, | ||
// we need to remove the indentation up to the first "/" of the comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand 'up to the first /'
I would think that if there is initial white space followed by a * and optional space but not a /, that text is removed.
There is initial white space and then one or more * and a / then that is a comment end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrased to
// we need to remove the indentation on every line.
// The length of removed indentation is maximum the space before the first "/*" + 3 characters
|
||
method test(d: D, t: T, e: Even) { | ||
// ^[Rich comment for D] | ||
// ^[D whose value is even] // Not working yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not working yet? A later PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It's another mechanism with symbols that needs to be fixed, maybe @keyboardDrummer who implemented jump to definition can figure out why there is no information on hovering the subset type T
and Even
function Test10(i: int): int | ||
/* Test10 computes an int | ||
It takes an int and adds 10 to it */ | ||
{ i + 1 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ i + 1 } | |
{ i + 10 } |
function Test11(i: int): int | ||
/** Test11 computes an int | ||
* It takes an int and adds 11 to it */ | ||
{ i + 1 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ i + 1 } | |
{ i + 11 } |
public void DocstringWorksForSubsetType() { | ||
DocstringWorksFor(@" | ||
type Odd = x: int | x % 2 == 1 witness 1 | ||
// Type of number that are not divisible by 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Type of number that are not divisible by 2 | |
// Type of numbers that are not divisible by 2 |
Source/DafnyCore/Generic/Node.cs
Outdated
// we need to remove the indentation up to the first "/" of the comment | ||
// Additionally, if there is a "* " or a " *" or a " * ", we remove it as well | ||
// provided it always started with a star. | ||
//var startIndex = match.Groups["multiline"].Index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these next two lines be deleted?
@@ -21,6 +23,11 @@ public interface ICanFormat : INode { | |||
bool SetIndent(int indentBefore, TokenNewIndentCollector formatter); | |||
} | |||
|
|||
// A node that can have a docstring attached to it | |||
public interface IHasDocstring : INode { | |||
string GetDocstring(DafnyOptions options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also have a method call GetDocstringSummary
that produces a summary (e.g. the first sentence) of the docstring. Certainly a dafny doc tool would need such, though it could be defined in that tool if you don't think other tools would need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To extract the first sentence, you need to do something non-trivial, such as detecting a period in the docstring, which seems arbitrary. We haven't discussed that the docstring should have one sentence first that indicates the summary (for example a good docstring could also be an example of API usage) hence I would prefer a dafny doc tool to define it by itself for the format of docstring it wants to support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll likely have more comments when I actually use it.
We gathered as a team last July to discuss how to add first-class support for Docstring, which is the interpretation of a special comment used for documentation purposes, e.g. hovering a symbol and getting more information about it.
We asked the following questions:
What entities will have docstrings attached to them?. We decided that, for now: fields, methods (also lemmas), functions (also predicates), datatypes, datatype constructors, opaque types, subset types, newtypes, classes, traits and export declarations would have a docstring associated to them.
We did not consider attaching docstring to function parameters yet, nor docstring to requires/ensures clause (but the
{:error}
attribute can help) so I leave these out of scope for now.What comment syntax to use for docstring?. We considered
//
,/* .. */
,///
and/** ... */
and concluded that, in places where a comment would never be present except if it were a docstring (see below), all comments would count as docstrings and be concatenated together. In places a comment could be present and might or might not be a docstring (e.g. //TODO...), we would only support/***/
kind of docstring.From what comments would docstring be extracted?.
Comments can be placed virtually between any two tokens in the code. There were essentially two ways to place comments so that they can be interpreted as doscstring: Either above the entity, or below the entity. It turns out that there was no consensus on which one would be preferred (50%-50% of voices for a quorum of 6). Placing the comment below looks more like a regular definition (here is the entity, here is the definition) and is taken by some languages (Python, Caml...), while placing it above is what some other languages like C# or Java do.
Our collective decision was to interpret comments placed below automatically as docstring first, because they are not ambiguous, and start to use it by default when writing Dafny ourselves. If not below, we would recognize comments above
/** ... */
as docstring.You will find below two same source code with the two different versions.
What syntax do we support for converting docstring?.
By default, we only remove comment signs and properly re-indent the docstring, but we do not process it further.
Because Dafny's currently supported IDE has VSCode whicih displays hover messages in Markdown, we expect users to write their docstring in Markdown though.
We also decided that we would enable a plugin-based rewriting of the docstring so that users can format it the way they want, and that Javadoc could be an example of such a plugin that we would provide as an example but not provide support for it, as users should relatively easily be able to override it.
Implementation
IHasDocstring
with the method.GetDocstring(DafnyOptions options)
All nodes implement the method but only a specific subset implement the interface. The docstrings are tested with respect to our decision in
DafnyPipeline
/*
+ two spaces, assuming the/*
is the first non-whitespace character of the line.--javadoclike-docstring-plugin
, which I hope will be activated by default when using the language server from a future version of VSCode. The goal is to provide a helper for those who are used to this syntax, not support the entire javadoc languageScreenshots
Additional notes
I can split this PR on demand if necessary.
Appendix
Docstring after/below entities - preferred choice (example)
Docstring before/above entities, also supported (example)
By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.