Skip to content

Commit

Permalink
Restrict autocomplete after "use" to only traits when in a class.
Browse files Browse the repository at this point in the history
Summary: When autocompleting after the "use" keyword, if it's in a class we shoud only return trait names.

Differential Revision: D7999875
  • Loading branch information
Will Pitts authored and fredemmott committed May 22, 2018
1 parent 2760d86 commit a4da482
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
33 changes: 30 additions & 3 deletions hphp/hack/src/server/autocompleteService.ml
Expand Up @@ -31,6 +31,7 @@ type autocomplete_type =
| Actype | Actype
| Acclass_get | Acclass_get
| Acprop | Acprop
| Actrait_only


let (argument_global_type: autocomplete_type option ref) = ref None let (argument_global_type: autocomplete_type option ref) = ref None
let auto_complete_for_global = ref "" let auto_complete_for_global = ref ""
Expand Down Expand Up @@ -118,6 +119,8 @@ let autocomplete_id id env = autocomplete_token Acid (Some env) id


let autocomplete_hint = autocomplete_token Actype None let autocomplete_hint = autocomplete_token Actype None


let autocomplete_trait_only = autocomplete_token Actrait_only None

let autocomplete_new cid env = let autocomplete_new cid env =
match cid with match cid with
| Nast.CI (sid, _) -> autocomplete_token Acnew (Some env) sid | Nast.CI (sid, _) -> autocomplete_token Acnew (Some env) sid
Expand Down Expand Up @@ -164,6 +167,7 @@ let should_complete_class completion_type class_kind =
| Some Acid, Some Ast.Cnormal | Some Acid, Some Ast.Cnormal
| Some Acid, Some Ast.Cabstract | Some Acid, Some Ast.Cabstract
| Some Acnew, Some Ast.Cnormal | Some Acnew, Some Ast.Cnormal
| Some Actrait_only, Some Ast.Ctrait
| Some Actype, Some _ -> true | Some Actype, Some _ -> true
| _ -> false | _ -> false


Expand Down Expand Up @@ -529,7 +533,7 @@ let autocomplete_typed_member ~is_static env class_ty cid mid =
let autocomplete_static_member env (ty, cid) mid = let autocomplete_static_member env (ty, cid) mid =
autocomplete_typed_member ~is_static:true env ty (Some cid) mid autocomplete_typed_member ~is_static:true env ty (Some cid) mid


class ['self] visitor = object (_ : 'self) class ['self] visitor = object (self : 'self)
inherit [_] Tast_visitor.iter as super inherit [_] Tast_visitor.iter as super


method! on_Id env id = method! on_Id env id =
Expand Down Expand Up @@ -579,6 +583,18 @@ class ['self] visitor = object (_ : 'self)
end end
end; end;
super#on_Xml env sid attrs el super#on_Xml env sid attrs el

method! on_class_ env cls =
List.iter cls.Tast.c_uses ~f:begin fun hint ->
match snd hint with
| Aast.Happly (sid, params) ->
autocomplete_trait_only sid;
List.iter params (self#on_hint env)
| _ -> ()
end;
(* If we don't clear out c_uses we'll end up overwriting the trait
completion as soon as we get to on_Happly. *)
super#on_class_ env {cls with Tast.c_uses = []}
end end


class ['self] auto_complete_suffix_finder = object (_ : 'self) class ['self] auto_complete_suffix_finder = object (_ : 'self)
Expand Down Expand Up @@ -667,21 +683,32 @@ let go
let completion_type = !argument_global_type in let completion_type = !argument_global_type in
if completion_type = Some Acid || if completion_type = Some Acid ||
completion_type = Some Acnew || completion_type = Some Acnew ||
completion_type = Some Actype completion_type = Some Actype ||
completion_type = Some Actrait_only
then compute_complete_global then compute_complete_global
~tcopt ~delimit_on_namespaces ~autocomplete_context ~content_funs ~content_classes; ~tcopt ~delimit_on_namespaces ~autocomplete_context ~content_funs ~content_classes;
if completion_type = Some Acprop then compute_complete_local tast; if completion_type = Some Acprop then compute_complete_local tast;
let env = match !ac_env with let env = match !ac_env with
| Some e -> e | Some e -> e
| None -> Typing_env.empty tcopt Relative_path.default ~droot:None | None -> Typing_env.empty tcopt Relative_path.default ~droot:None
in in
let filter_results (result: autocomplete_result) : bool =
let kind = match result with
| Partial res -> res.kind_
| Complete res -> res.res_kind
in
match completion_type, kind with
| Some Actrait_only, Trait_kind -> true
| Some Actrait_only, _ -> false
| _ -> true
in
let resolve (result: autocomplete_result) : complete_autocomplete_result = let resolve (result: autocomplete_result) : complete_autocomplete_result =
match result with match result with
| Partial res -> resolve_ty env autocomplete_context res ~delimit_on_namespaces | Partial res -> resolve_ty env autocomplete_context res ~delimit_on_namespaces
| Complete res -> res | Complete res -> res
in in
{ {
With_complete_flag.is_complete = !autocomplete_is_complete; With_complete_flag.is_complete = !autocomplete_is_complete;
value = !autocomplete_results |> List.map ~f:resolve; value = !autocomplete_results |> List.filter ~f:filter_results |> List.map ~f:resolve;
} }
end end
8 changes: 8 additions & 0 deletions hphp/hack/test/autocomplete/use_trait.php
@@ -0,0 +1,8 @@
<?hh // strict
class MyAutocompleteAfterUse {
use MyAUTO332
}

trait MyTrait {

}
1 change: 1 addition & 0 deletions hphp/hack/test/autocomplete/use_trait.php.exp
@@ -0,0 +1 @@
MyTrait trait

0 comments on commit a4da482

Please sign in to comment.