-
Notifications
You must be signed in to change notification settings - Fork 31
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
Add support for default values to TYPEDSIGNATURES
#170
Open
JamesWrigley
wants to merge
13
commits into
JuliaDocs:master
Choose a base branch
from
JamesWrigley:default-values
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b22f594
Fix tests on 1.11
JamesWrigley 617ae4a
Add support for default values to `TYPEDSIGNATURES`
JamesWrigley 1c80865
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley 594593e
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley de0f36b
Combine TypedMethodSignatures and MethodSignatures
JamesWrigley d1b97f7
Delete obsolete template_hook() method
JamesWrigley fe01fe3
Make the Expr optional for MethodSignatures
JamesWrigley 1532071
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley 7fed390
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley f1c9145
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley 1efecf6
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley 79783e4
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley ebb95a9
fixup! Add support for default values to `TYPEDSIGNATURES`
JamesWrigley File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
Base.@kwdef struct ASTArg | ||
name::Union{Symbol, Nothing} = nothing | ||
type = nothing | ||
default = nothing | ||
variadic::Bool = false | ||
end | ||
|
||
# Parse an argument with a type annotation. | ||
# Example input: `x::Int` | ||
function parse_arg_with_type(arg_expr::Expr) | ||
if arg_expr.head != :(::) | ||
throw(ArgumentError("Argument is not a :(::) expr")) | ||
end | ||
|
||
n_expr_args = length(arg_expr.args) | ||
return if n_expr_args == 1 | ||
# '::Int' | ||
ASTArg(; type=arg_expr.args[1]) | ||
elseif n_expr_args == 2 | ||
# 'x::Int' | ||
ASTArg(; name=arg_expr.args[1], type=arg_expr.args[2]) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding an explicit failure branch here (even though we know that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, added in f1c9145. |
||
end | ||
|
||
# Parse an argument with a default value. | ||
# Example input: `x=5` | ||
function parse_arg_with_default(arg_expr::Expr) | ||
if arg_expr.head != :kw | ||
throw(ArgumentError("Argument is not a :kw expr")) | ||
end | ||
|
||
if arg_expr.args[1] isa Symbol | ||
# This is an argument without a type annotation | ||
ASTArg(; name=arg_expr.args[1], default=arg_expr.args[2]) | ||
else | ||
# This is an argument with a type annotation | ||
tmp = parse_arg_with_type(arg_expr.args[1]) | ||
ASTArg(; name=tmp.name, type=tmp.type, default=arg_expr.args[2]) | ||
end | ||
end | ||
|
||
# Parse a list of expressions, assuming the list is an argument list containing | ||
# positional/keyword arguments. | ||
# Example input: `(x, y::Int; z=5, kwargs...)` | ||
function parse_arglist!(exprs, args, kwargs, is_kwarg_list=false) | ||
list = is_kwarg_list ? kwargs : args | ||
|
||
for arg_expr in exprs | ||
if arg_expr isa Symbol | ||
# Plain argument name with no type or default value | ||
push!(list, ASTArg(; name=arg_expr)) | ||
elseif arg_expr.head == :(::) | ||
# With a type annotation | ||
push!(list, parse_arg_with_type(arg_expr)) | ||
elseif arg_expr.head == :kw | ||
# With a default value (and possibly a type annotation) | ||
push!(list, parse_arg_with_default(arg_expr)) | ||
elseif arg_expr.head == :parameters | ||
# Keyword arguments | ||
parse_arglist!(arg_expr.args, args, kwargs, true) | ||
elseif arg_expr.head === :... | ||
# Variadic argument | ||
if arg_expr.args[1] isa Symbol | ||
# Without a type annotation | ||
push!(list, ASTArg(; name=arg_expr.args[1], variadic=true)) | ||
elseif arg_expr.args[1].head === :(::) | ||
# With a type annotation | ||
arg_expr = arg_expr.args[1] | ||
push!(list, ASTArg(; name=arg_expr.args[1], type=arg_expr.args[2], variadic=true)) | ||
else | ||
Meta.dump(arg_expr) | ||
error("Couldn't parse variadic Expr in arg list (printed above)") | ||
end | ||
else | ||
Meta.dump(arg_expr) | ||
error("Couldn't parse Expr in arg list (printed above)") | ||
end | ||
end | ||
end | ||
|
||
# Find a :call expression within an Expr. This will take care of ignoring other | ||
# tokens like `where` clauses. | ||
function find_call_expr(expr::Expr) | ||
if expr.head === :macrocall && expr.args[1] === Symbol("@generated") | ||
# If this is a generated function, find the first := expr to find | ||
# the :call expr. | ||
assignment_idx = findfirst(x -> x isa Expr && x.head === :(=), expr.args) | ||
|
||
expr.args[assignment_idx].args[1] | ||
elseif expr.head === :(=) | ||
find_call_expr(expr.args[1]) | ||
elseif expr.head == :where | ||
# Function with one or more `where` clauses | ||
find_call_expr(expr.args[1]) | ||
elseif expr.head === :function | ||
find_call_expr(expr.args[1]) | ||
elseif expr.head === :call | ||
expr | ||
else | ||
Meta.dump(expr) | ||
error("Can't parse current expr (printed above)") | ||
end | ||
end | ||
|
||
# Parse an expression to find a :call expr, and return as much information as | ||
# possible about the arguments. | ||
# Example input: `foo(x) = x^2` | ||
function parse_call(expr::Expr) | ||
Base.remove_linenums!(expr) | ||
expr = find_call_expr(expr) | ||
|
||
if expr.head != :call | ||
throw(ArgumentError("Argument is not a :call, cannot parse it.")) | ||
end | ||
|
||
args = ASTArg[] | ||
kwargs = ASTArg[] | ||
# Skip the first argument because that's just the function name | ||
parse_arglist!(expr.args[2:end], args, kwargs) | ||
|
||
return (; args, kwargs) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
There's
Meta.isexpr
which would be preferable to use to keep things consistent instead of reaching into the.head
field.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.
Same applies to elsewhere that uses
.head ==
comparisons.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.
Good point, fixed in 1c80865.