@@ -49,13 +49,13 @@ function get_hover(b::StaticLint.Binding, documentation::String, server)
4949 else
5050 documentation = try
5151 documentation = if binding_has_preceding_docs (b)
52- string (documentation, to_codeobject (parentof (b. val). args[3 ]))
52+ string (documentation, to_codeobject (maybe_get_doc_expr (b. val). args[3 ]))
5353 elseif const_binding_has_preceding_docs (b)
54- string (documentation, to_codeobject (parentof (parentof (b. val)). args[3 ]))
54+ string (documentation, to_codeobject (maybe_get_doc_expr (parentof (b. val)). args[3 ]))
5555 else
5656 documentation
5757 end
58- documentation = string (documentation, " ```julia\n " , prettify_expr (to_codeobject (b. val)), " \n ```\n " )
58+ documentation = string (ensure_ends_with ( documentation) , " ```julia\n " , prettify_expr (to_codeobject (b. val)), " \n ```\n " )
5959 catch err
6060 @error " get_hover failed to convert Expr" exception = (err, catch_backtrace ())
6161 throw (LSHoverError (string (" get_hover failed to convert Expr" )))
@@ -128,9 +128,9 @@ get_func_hover(x::SymbolServer.SymStore, documentation, server) = get_hover(x, d
128128
129129function get_preceding_docs (expr:: EXPR , documentation)
130130 if expr_has_preceding_docs (expr)
131- string (documentation, to_codeobject (parentof (expr). args[3 ]))
131+ string (documentation, to_codeobject (maybe_get_doc_expr (expr). args[3 ]))
132132 elseif is_const_expr (parentof (expr)) && expr_has_preceding_docs (parentof (expr))
133- string (documentation, to_codeobject (parentof (parentof (expr)). args[3 ]))
133+ string (documentation, to_codeobject (maybe_get_doc_expr (parentof (expr)). args[3 ]))
134134 else
135135 documentation
136136 end
@@ -145,18 +145,28 @@ function const_binding_has_preceding_docs(b::StaticLint.Binding)
145145 is_const_expr (p) && expr_has_preceding_docs (p)
146146end
147147
148+ function maybe_get_doc_expr (x)
149+ # The expression may be nested in any number of macros
150+ while CSTParser. hasparent (x) &&
151+ CSTParser. ismacrocall (parentof (x))
152+ x = parentof (x)
153+ headof (x. args[1 ]) === :globalrefdoc && return x
154+ end
155+ return x
156+ end
157+
148158expr_has_preceding_docs (x) = false
149- expr_has_preceding_docs (x:: EXPR ) = is_doc_expr (parentof (x))
159+ expr_has_preceding_docs (x:: EXPR ) = is_doc_expr (maybe_get_doc_expr (x))
150160
151161is_const_expr (x) = false
152162is_const_expr (x:: EXPR ) = headof (x) === :const
153163
154164is_doc_expr (x) = false
155165function is_doc_expr (x:: EXPR )
156166 return CSTParser. ismacrocall (x) &&
157- length (x. args) == 4 &&
158- headof (x. args[1 ]) === :globalrefdoc &&
159- CSTParser. isstring (x. args[3 ])
167+ length (x. args) == 4 &&
168+ headof (x. args[1 ]) === :globalrefdoc &&
169+ CSTParser. isstring (x. args[3 ])
160170end
161171
162172get_fcall_position (x, documentation, visited= nothing ) = documentation
@@ -187,7 +197,7 @@ function get_fcall_position(x::EXPR, documentation, visited=Set{EXPR}())
187197
188198 fname = CSTParser. get_name (parentof (x))
189199 if StaticLint. hasref (fname) &&
190- (refof (fname) isa StaticLint. Binding && refof (fname). val isa EXPR && CSTParser. defines_struct (refof (fname). val) && StaticLint. struct_nargs (refof (fname). val)[1 ] == minargs)
200+ (refof (fname) isa StaticLint. Binding && refof (fname). val isa EXPR && CSTParser. defines_struct (refof (fname). val) && StaticLint. struct_nargs (refof (fname). val)[1 ] == minargs)
191201 dt_ex = refof (fname). val
192202 args = dt_ex. args[3 ]
193203 args. args === nothing || arg_i > length (args. args) && return documentation
0 commit comments