Skip to content
Merged
39 changes: 39 additions & 0 deletions analysis/src/CompletionFrontEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,45 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
(* Case foo-> when the parser adds a ghost expression to the rhs
so the apply expression does not include the cursor *)
if setPipeResult ~lhs ~id:"" then setFound ()
(*
A dot completion for a tagged templated application.
Example:
sh`echo "meh"`.
or
sh`bar`.len
*)
| Pexp_apply
{
funct = {pexp_desc = Pexp_ident {txt = Lident "."; loc = _}};
args =
[(_, ({pexp_desc = Pexp_apply _} as innerExpr)); (_, fieldExpr)];
}
when Res_parsetree_viewer.is_tagged_template_literal innerExpr
&& expr.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor
|| CompletionExpressions.isExprHole fieldExpr ->
exprToContextPath innerExpr
|> Option.iter (fun cpath ->
(* Determine the field name if present *)
let fieldName =
match fieldExpr.pexp_desc with
| Pexp_ident {txt = Lident fieldName}
when Res_parsetree_viewer.is_tagged_template_literal innerExpr
->
fieldName
(* This is likely to be an exprhole *)
| _ -> ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could add the explicit match (or an if branch using the utils we have for expr holes) just to make the code a bit clearer in what we care about in the AST. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against having an explicit match, but I don't know what else to return when it is anything else, that is why I went with | _ -> "".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that'd remain, you'd just also add the explicit match for clarity, even though it's redundant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split them after al.
Seems most clear to me.

in

setResult
(Cpath
(CPField
{
contextPath = cpath;
fieldName;
posOfDot;
exprLoc = expr.pexp_loc;
}));
setFound ())
| _ -> (
if expr.pexp_loc |> Loc.hasPos ~pos:posNoWhite && !result = None then (
setFound ();
Expand Down
8 changes: 8 additions & 0 deletions tests/analysis_tests/tests/src/CompletionTaggedTemplate.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@module("meh") @taggedTemplate
external meh: (array<string>, array<string>) => string = "default"

// let x = meh`foo`.
// ^com

// let y = meh`bar`.len
// ^com
Loading