2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
13 let symbols_at (file
, line
, char
) tcopt
=
14 let contents = match file
with
15 | ServerCommandTypes.FileName file_name
->
16 let relative_path = Relative_path.(create Root file_name
) in
17 File_provider.get_contents
relative_path
18 | ServerCommandTypes.FileContent content
-> Some content
22 | Some
contents -> ServerIdentifyFunction.go
contents line char tcopt
24 let type_at (file
, line
, char
) tcopt naming_table
=
27 GlobalOptions.tco_dynamic_view
= ServerDynamicView.dynamic_view_on
();
29 let _, tast
= ServerIdeUtils.check_file_input
tcopt naming_table file
in
30 let env_ty_opt = ServerInferType.type_at_pos tast line char
in
31 Option.map
env_ty_opt ~f
:(fun (env
, ty
) -> env
, Tast_expand.expand_ty env ty
)
33 (** When we get a Class occurrence and a Method occurrence, that means that the
34 user is hovering over an invocation of the constructor, and would therefore only
35 want to see information about the constructor, rather than getting both the
36 class and constructor back in the hover. *)
37 let filter_class_and_constructor results
=
38 let result_is_constructor result
=
39 SymbolOccurrence.is_constructor
(fst result
) in
40 let result_is_class result
=
41 SymbolOccurrence.is_class
(fst result
) in
42 let has_class = List.exists results ~f
:result_is_class in
43 let has_constructor = List.exists results ~f
:result_is_constructor in
44 if has_class && has_constructor
45 then List.filter results ~f
:result_is_constructor
48 let make_hover_doc_block ~basic_only file occurrence def_opt
=
51 let base_class_name = SymbolOccurrence.enclosing_class occurrence
in
52 ServerDocblockAt.go_def ~def ~
base_class_name ~file ~basic_only
56 let make_hover_return_type env_and_ty occurrence
=
57 let open SymbolOccurrence
in
58 let open Typing_defs
in
59 match occurrence
, env_and_ty
with
60 | { type_
= Function
| Method
_; _ }, Some
(env
, (_, Tfun ft
)) ->
61 [Printf.sprintf
"Return type: `%s`" (Tast_env.print_ty env ft
.ft_ret
)]
64 let make_hover_full_name env_and_ty occurrence def_opt
=
65 let open SymbolOccurrence
in
66 let open Typing_defs
in
67 match occurrence
, env_and_ty
with
68 | { type_
= Method
_; _ }, _
69 | { type_
= Property
_ | ClassConst
_; _ }, Some
(_, (_, Tfun
_)) ->
70 let name = match def_opt
with
71 | Some def
-> def
.SymbolDefinition.full_name
72 | None
-> occurrence
.name
74 [Printf.sprintf
"Full name: `%s`" (Utils.strip_ns
name)]
77 let make_hover_info env_and_ty file
(occurrence
, def_opt
) ~basic_only
=
78 let open SymbolOccurrence
in
79 let open Typing_defs
in
80 let snippet = match occurrence
, env_and_ty
with
81 | { name; _ }, None
-> Utils.strip_ns
name
82 | { type_
= Method
(classname
, name); _ }, Some
(env
, ty
)
83 when name = Naming_special_names.Members.__construct
->
85 let open Option.Monad_infix
in
86 Decl_provider.get_class classname
87 >>= fun c
-> fst
(Decl_provider.Class.construct c
)
89 let ty = Lazy.force_val elt
.ce_type
in
90 Tast_env.print_ty_with_identity env
ty occurrence def_opt
92 begin match snippet_opt with
94 | None
-> Tast_env.print_ty_with_identity env
ty occurrence def_opt
96 | occurrence
, Some
(env
, ty) -> Tast_env.print_ty_with_identity env
ty occurrence def_opt
98 let addendum = List.concat
[
99 make_hover_doc_block file occurrence def_opt ~basic_only
;
100 make_hover_return_type env_and_ty occurrence
;
101 make_hover_full_name env_and_ty occurrence def_opt
;
104 HoverService.{ snippet; addendum; pos
= Some occurrence
.SymbolOccurrence.pos
}
106 let go env
(file
, line
, char
) ~basic_only
=
107 let position = (file
, line
, char
) in
108 let ServerEnv.{ tcopt; naming_table
; _ } = env
in
109 let identities = symbols_at position tcopt in
110 let env_and_ty = type_at position tcopt naming_table
in
111 (* There are legitimate cases where we expect to have no identities returned,
112 so just format the type. *)
113 match identities with
115 begin match env_and_ty with
117 [{ snippet = Tast_env.print_ty env
ty; addendum = []; pos
= None
}]
122 |> filter_class_and_constructor
123 |> List.map ~f
:(make_hover_info env_and_ty file ~basic_only
)
124 |> List.remove_consecutive_duplicates ~equal
:(=)