-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Better support for documenting expressions with macros #12000
Conversation
Updated and |
I could also just document the object if the argument is a macro call but it will fail if this is a macro definition (which probably doesn't matter) and it won't be able to track function signature julia> """
(Float64)
"""
@inline f(::Float64) = 1
f (generic function with 1 method)
julia> """
(Int)
"""
@inline f(::Int) = 1
f (generic function with 2 methods)
help?> f(1)
f(::Int64) at none:4
help?> f
search: f fd for fma fld fft full find filt fill fft! fdio frexp foldr foldl flush
(Int) |
I'm uncomfortable with making zero-arg macro calls a special case like this. It's very fiddly to need to switch to |
So probably
Edit: and by kept I mean |
That sounds better. |
There's still the inconsistency that This is the inconsistency I'm trying to address with the 0-argument special case but I guess since it cannot be made fully consistent with everything anyway, I might as well make the implementation simpler.... |
Oh, and another issue is that I cannot distinguish Now I remember why exactly I implement it this way...
This itself will require a special case for 0-argument macrocall. Furthermore, if there's no special case for this in the parser, Another way out of this is to make bare string literal document to be lowered to a different internal macro that has different handling of macrocall. This also has the advantage that we and independently tweak the behavior of each one. |
In short, in order to get the behavior I mentioned above #12000 (comment) (which I probably the most intuitive one I can think of) |
The behavior should be the same with the I described above now. Here's a compilation of the current behavior (with this PR) julia> macro id(f)
esc(f)
end
julia> macro m(args...)
println(args)
end
# Documenting @id
julia> @doc """
identity
""" @id
(anonymous function)
# This is a normal macro call so having a new line does not work
julia> @doc """
print
"""
@m
()
help?> @id
identity
# @m is not documented yet as can be seen from the printing of from @m and the error below
help?> @m
Symbol not found. Falling back on apropos search ...
No help information found.
# Still won't work because this document the expansion of @m, which is `nothing`
julia> """
print
""" @m
()
# As shown here
help?> @m
Symbol not found. Falling back on apropos search ...
No help information found.
# This is the only way to document a macro after it's definition (AFAICT)
julia> @doc """
print
""" @m
(anonymous function)
# And it works
help?> @m
print
# Documenting function definition "decorated" with macros
julia> """
(Int)
"""
@inline f(::Int) = 1
f (generic function with 1 method)
julia> """
(Float64)
"""
@inline f(::Float64) = 1
f (generic function with 2 methods)
# And the methods are documented correctly
help?> f(1)
(Int)
# Also for the whole function
help?> f
search: f fd for fma fld fft full find filt fill fft! fdio frexp foldr foldl flush floor float first findn filt! fill! fetch FFTW flipud fliplr fldmod findnz findin
(Int)
(Float64)
# Works as expected
julia> """
"""
@id immutable bar
x::Int
end
julia> bar(1)
bar(1)
# Empty doc string. Ooops.
help?> bar
search: bar baremodule SubArray GlobalRef clipboard BitArray backtrace find_library mmap_bitarray BitMatrix takebuf_array catch_backtrace AbstractRNG AbstractArray
# Try again with a different type, now with non-empty doc string.
julia> """
bar
"""
@id immutable baz
x::Int
end
# And it works.
help?> baz
search: baz
bar |
My use case would be to document types defined in macros:
so this should document the new type:
would this work with this PR? (Sorry for being lazy and not just trying it out!) I.e. does it alway document the first item defined with the macro or something else? |
NP. I don't always like to wait for ~10min to compile someone else's PR either.... :P
Not directly and not on current master either because
This works. julia> macro mkT(f)
quote
immutable $f end
g() = 5
$f
end
end
julia> @doc """
My T1
""" @mkT T1
T1
julia> """
My T2
"""
@mkT T2
T2
help?> T1
search: T1 Int16 int16 Int128 rot180 int128 UInt16 uint16 Uint16 UInt128 uint128
My T1
help?> T2
search: T2 hist2d hist2d! Int32 int32 Int128 int128 UInt32 uint32 Uint32 UInt128
My T2 The expansion of the macro is not a single type definition so P.S. The only exception to the above rules are macro definition (which doesn't return anything) and function definition (which returns the function and not the method, a behavior that is useful in many cases). In these cases, you would have to let |
If the macro expander function were exposed in a more first-class way, then that would be a natural thing to attach the docstring to (in fact, I'm pretty sure this is how it actually works under the hood). |
@StefanKarpinski Sorry I think I don't quite understand what you mean here. What is "a more first-class way" (or why it is not first class now) and this is how what works under the hood? |
The zero-arg case was from when we couldn't add docstrings to most places in base prior to @one-more-minute's """
...
"""
macro m()
# ...
end anywhere wouldn't it be better to just remove the zero-arg case and require macros to be documented at the definition site? I realise that That would remove the ambiguity and leave |
So what about this (
I'm using See commit 29a8eea @one-more-minute @MichaelHatherly |
+1 |
Fixed. Thanks. Also fixed the tests... |
A bit slow to respond. So, if I wanted to document a method defined within a macro I would need to do:
Right? (edited to reflect @yuyichao's correction) |
@mauro3 I guess you meant two There still can't be a new line after the doc string if you use the I don't think there's currently a way to document a method after it's defined (although I might be wrong). It's probably possible to add support for that (and we should) but that's not in the scope of this PR. |
Well, if you defined multiple methods (or multiple objects to be documented) in a single macro, there isn't anything the doc system can help with that (unless you call If you are just worrying about multiple methods of a single function, it shouldn't be too bad since |
Thanks for the clarification. Works for me. |
The document for the |
Just realized that I can do manual TCO for |
@@ -201,7 +201,7 @@ end | |||
|
|||
doc(f, ::Method) = doc(f) | |||
|
|||
# Modules | |||
# Modules |
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.
This is pretty weird, have we somehow ended up with a different kind of space here?
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.
It's a non-breaking space. We have a lot of them.
I have an old PR to clean them up but I still need to rebase it and check if any of them are used intentionally.
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.
Ref #11605
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 assume that must be my fault, although I have no idea why an editor would insert one of those.
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.
Editor shortcut probably?
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.
Ah yes, looks like Alt-Space does it on OS X – better watch out for that one.
I imagine there are many people who would want to see a manual implementation of TCO, but I'm definitely not one of them :) As a bonus we throw an error when people try to documenting infinite expressions, rather than hanging. Anyway, LGTM, I'll wait on the tests. |
@tkelman I guess the push failure is sth know and is fixed now? |
yeah, fixed by 896cadf |
Since this seems to be getting ready for merging, I created a |
Would this need documenting too? |
I didn't bother add doc yet mainly because this wasn't a documented interface to begin with and originally this change distinguish between documenting with or without This isn't the case anymore so if everyone is happy about the current state I'll add some document about the change soon. |
Added a section about documenting after an object is defined in the documentation of |
I'm wondering if it'd be a good idea to put ExpressionMatch.jl into Base. Especially if we start adding more syntax to julia> @match :(:@time) begin
:(@f_) -> "macro $f"
:(f_"") -> "string macro $f"
end
"macro @time"
julia> @match :(:(r"")) begin
:(@f_) -> "macro $f"
:(f_"") -> "string macro $f"
end
"string macro @r_str" |
I'm not an expert on what should go into base. But I'd say not this PR for sure.
Well, OTOH, making it harder to add syntax also makes it harder to introduce breaking changes and obscure syntax. It took me a long time to convince myself that it is ok to add new syntax like this and I hope this should happen as infrequent as possible. |
Sure, definitely not for this PR. I just introduced a merge conflict (sorry), but if you can rebase this I'll merge then. |
1. Always do macro expansion in @doc 2. Use `@doc "<doc string>" :@macro` to document macros after definition 3. Unblock recursively
I can tell you merge that PR just to post this comment 😆 It's a stupid end-of-test-file conflict. |
Nothing interesting has changed since this passed the tests before, right? I'd really like to start working off these changes. |
@one-more-minute There shouldn't be. The AppVeyor test should be done in a few minutes so I would suggest waiting for a few more minutes rather than being ping'd by Tony if sth unexpected happened. |
Better support for documenting expressions with macros
Awesome, really glad we have a better approach for this now. |
@IainNZ Could you please check if this causes any breakage in packages? Depending on how bad it is we can either merge or discard JuliaLang/Compat.jl#113 |
Fix #11993 (not sure if this is the best way though)
Update:
See below for the current behavior Better support for documenting expressions with macros #12000 (comment) and examples of it Better support for documenting expressions with macros #12000 (comment)
It still uses
macroexpand
in amacro
.Original post:
Disallow documenting macro with
syntax since it can be ambiguous with expanding and using the macro (which might have side effects)
Expand the macro if the expression to be documented is a macro call in order to document the correct object.
Issues
This is calling
macroexpand
in a macro. Not sure if this is the best thing to do but I couldn't come up with a better way to do what I want.Both"" @m
and""<\n>@m
areis parsed asThe former should probably be reallowed,(edit: fixed)the latterthis should probably not have theblock
(although I couldn't figure out if I can reset the input stream)