Skip to content

Commit

Permalink
Add an action for adding a docstring snippet with the method signatur…
Browse files Browse the repository at this point in the history
…e to a method definition.
  • Loading branch information
fredrikekre committed May 20, 2022
1 parent eed8507 commit 3ed0d38
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/requests/actions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,45 @@ function convert_from_raw(x, _, conn)
return nothing
end

# Checks if parent is a parent/grandparent/... of child
function is_parent_of(parent::EXPR, child::EXPR)
while child isa EXPR
if child == parent
return true
end
child = child.parent
end
return false
end

function is_in_function_signature(x::EXPR, params; with_docstring=false)
# TODO: Perhaps also allow this if the cursor is inside a docstring?
func = _get_parent_fexpr(x, CSTParser.defines_function)
func === nothing && return false
sig = func.args[1]
if x.head === :FUNCTION || is_parent_of(sig, x)
hasdoc = func.parent isa EXPR && func.parent.head === :macrocall && func.parent.args[1] isa EXPR &&
func.parent.args[1].head === :globalrefdoc
return with_docstring == hasdoc
end
return false
end

function add_docstring_template(x, _, conn)
is_in_function_signature(x, nothing) || return
func = _get_parent_fexpr(x, CSTParser.defines_function)
func === nothing && return
file, func_offset = get_file_loc(func)
sig = func.args[1]
_, sig_offset = get_file_loc(sig)
docstr = "\"\"\"\n " * get_text(file)[sig_offset .+ (1:sig.span)] * "\n\nTBW\n\"\"\"\n"
tde = TextDocumentEdit(VersionedTextDocumentIdentifier(get_uri(file), get_version(file)), TextEdit[
TextEdit(Range(file, func_offset:func_offset), docstr)
])
JSONRPC.send(conn, workspace_applyEdit_request_type, ApplyWorkspaceEditParams(missing, WorkspaceEdit(missing, TextDocumentEdit[tde])))
return
end

# Adding a CodeAction requires defining:
# * a unique id
# * a description
Expand Down Expand Up @@ -682,3 +721,12 @@ LSActions["RewriteAsRegularString"] = ServerAction(
(x, _) -> is_string_literal(x; inraw=true),
convert_from_raw,
)

LSActions["AddDocstringTemplate"] = ServerAction(
"AddDocstringTemplate",
"Add docstring template for this method",
missing,
missing,
is_in_function_signature,
add_docstring_template,
)
43 changes: 43 additions & 0 deletions test/requests/actions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,48 @@ end
raw_str = "he\$l\"lo"
str = "\"he\\\$l\\\"lo\"" # Will be `"he\$l\"lo` when unescaped/printed
@test repr(raw_str) == str
end

@testset "Add docstring template" begin
doc = settestdoc("""
f(x) = x
@inline f(x) = x
f(x::T) where T <: Int = x
function g(x)
end
function g(x::T) where T <: Int
end
"docstring"
h(x) = x
"docstring"
function h(x)
end
""")

ok_locations = [
[(0, i) for i in 0:3],
[(2, i) for i in 8:11],
[(4, i) for i in 0:21],
[(6, i) for i in 0:12],
[(9, i) for i in 0:30],
]
not_ok_locations = [
[(13, i) for i in 0:4],
[(16, i) for i in 0:12],
]
for loc in Iterators.flatten(ok_locations)
@test any(c.command == "AddDocstringTemplate" for c in action_request_test(loc...))
end
for loc in Iterators.flatten(not_ok_locations)
@test !any(c.command == "AddDocstringTemplate" for c in action_request_test(loc...))
end

c = filter(c -> c.command == "AddDocstringTemplate", action_request_test(0, 1))[1]
LanguageServer.workspace_executeCommand_request(LanguageServer.ExecuteCommandParams(missing, c.command, c.arguments), server, server.jr_endpoint)
end

0 comments on commit 3ed0d38

Please sign in to comment.