Fix special case of alternate if statements
[hiphop-php.git] / hphp / hack / src / server / serverHighlightRefs.ml
bloba30ff8c8bf4ddfb338a154648b95dac7a13a0aa5
1 (**
2 * Copyright (c) 2016, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 open Hh_core
12 let get_target symbol =
13 let open SymbolOccurrence in
14 let module Types = ServerCommandTypes.Find_refs in
15 let open FindRefsService in
16 match symbol.type_ with
17 | SymbolOccurrence.Class -> Some (IClass symbol.name)
18 | SymbolOccurrence.Function -> Some (IFunction symbol.name)
19 | SymbolOccurrence.Method (class_name, member_name) ->
20 Some (IMember (Subclasses_of class_name,
21 Types.Method member_name))
22 | SymbolOccurrence.Property (class_name, member_name) ->
23 Some (IMember (Subclasses_of class_name,
24 Types.Property member_name))
25 | SymbolOccurrence.ClassConst (class_name, member_name) ->
26 Some (IMember (Subclasses_of class_name,
27 Types.Class_const member_name))
28 | SymbolOccurrence.Typeconst (class_name, member_name) ->
29 Some (IMember (Subclasses_of class_name,
30 Types.Typeconst member_name))
31 | SymbolOccurrence.GConst -> Some (IGConst symbol.name)
32 | _ -> None
34 let highlight_symbol tcopt (line, char) path file_info symbol =
35 let res = match get_target symbol with
36 | Some target ->
37 let results = FindRefsService.find_refs
38 tcopt target [] [(path, file_info)] in
39 List.rev (List.map results snd)
40 | None when symbol.SymbolOccurrence.type_ = SymbolOccurrence.LocalVar ->
41 begin match Parser_heap.ParserHeap.get path with
42 | Some (ast, _) -> ServerFindLocals.go_from_ast ast line char
43 | None -> []
44 end
45 | None -> []
47 List.map res Ide_api_types.pos_to_range
49 let filter_result symbols result =
50 let result = List.fold symbols ~init:result ~f:(fun result symbol ->
51 if (Pos.length symbol.SymbolOccurrence.pos >
52 Pos.length result.SymbolOccurrence.pos)
53 then result
54 else symbol) in
55 List.filter symbols ~f:(fun symbol ->
56 symbol.SymbolOccurrence.pos = result.SymbolOccurrence.pos)
58 let compare r1 r2 =
59 let open Ide_api_types in
60 let s1, s2 = r1.st, r2.st in
61 if s1.line < s2.line then -1
62 else if s1.line > s2.line then 1
63 else if s1.column < s2.column then -1
64 else if s1.column > s2.column then 1
65 else 0
67 let rec combine_result l l1 l2 =
68 match l1, l2 with
69 | l1, [] ->
70 l @ l1
71 | [], l2 ->
72 l @ l2
73 | h1 :: l1_, h2 :: l2_ ->
74 begin
75 match compare h1 h2 with
76 | -1 -> combine_result (l @ [h1]) l1_ l2
77 | 1 -> combine_result (l @ [h2]) l1 l2_
78 | 0 -> combine_result (l @ [h1]) l1_ l2_
79 | _ -> l
80 end
82 let go (content, line, char) tcopt =
83 ServerIdentifyFunction.get_occurrence_and_map tcopt content line char
84 ~f:begin fun path file_info symbols ->
85 match symbols with
86 | symbol::_ ->
87 let symbols = filter_result symbols symbol in
88 List.fold symbols ~init:[] ~f:(fun acc symbol ->
89 combine_result [] acc
90 (highlight_symbol tcopt (line, char) path file_info symbol))
91 | _ -> []
92 end