Fill in to_oxidized for a few more fields in FoldedClass
[hiphop-php.git] / hphp / hack / src / hh_parse.ml
bloba9ee7cc773397f2ea5e25482383d466a74f29147
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 (**
12 * Usage: hh_parse [OPTIONS] [FILES]
14 * --full-fidelity-json
15 * --full-fidelity-json-parse-tree
16 * --full-fidelity-errors
17 * --full-fidelity-errors-all
18 * --full-fidelity-ast-s-expression
19 * --program-text
20 * --pretty-print
21 * --pretty-print-json
22 * --show-file-name
24 * TODO: Parser for things other than scripts:
25 * types, expressions, statements, declarations, etc.
28 module Schema = Full_fidelity_schema
29 module SyntaxError = Full_fidelity_syntax_error
30 module SyntaxTree =
31 Full_fidelity_syntax_tree.WithSyntax (Full_fidelity_positioned_syntax)
32 module SourceText = Full_fidelity_source_text
33 module ParserErrors =
34 Full_fidelity_parser_errors.WithSyntax (Full_fidelity_positioned_syntax)
35 open FullFidelityParseArgs
37 (* Prints a single FFP error. *)
38 let print_full_fidelity_error source_text error =
39 let text =
40 SyntaxError.to_positioned_string
41 error
42 (SourceText.offset_to_position source_text)
44 Printf.printf "%s\n" text
46 let print_ast_check_errors errors =
47 let error_list = Errors.get_error_list errors in
48 List.iter
49 (fun e ->
50 let text = Errors.to_string (User_error.to_absolute e) in
52 Core_kernel.String.is_substring
53 text
54 ~substring:SyntaxError.this_in_static
55 || Core_kernel.String.is_substring
56 text
57 ~substring:SyntaxError.toplevel_await_use
58 then
59 Printf.eprintf "%s\n%!" text)
60 error_list
62 let handle_existing_file args filename =
63 let popt = FullFidelityParseArgs.to_parser_options args in
64 (* Parse with the full fidelity parser *)
65 let file = Relative_path.create Relative_path.Dummy filename in
66 let source_text = SourceText.from_file file in
67 let mode = Full_fidelity_parser.parse_mode source_text in
68 let print_errors =
69 args.codegen || args.full_fidelity_errors || args.full_fidelity_errors_all
71 let env =
72 FullFidelityParseArgs.to_parser_env
73 (* When print_errors is true, the leaked tree will be passed to ParserErrors,
74 * which will consume it. *)
75 ~leak_rust_tree:print_errors
76 ~mode
77 args
79 let syntax_tree = SyntaxTree.make ~env source_text in
80 let editable = SyntaxTransforms.editable_from_positioned syntax_tree in
81 if args.show_file_name then Printf.printf "%s\n" filename;
82 (if args.program_text then
83 let text = Full_fidelity_editable_syntax.text editable in
84 Printf.printf "%s\n" text);
85 (if args.pretty_print then
86 let pretty = Libhackfmt.format_tree syntax_tree in
87 Printf.printf "%s\n" pretty);
88 (if args.generate_hhi then
89 let hhi = Generate_hhi.go editable in
90 Printf.printf "%s\n" hhi);
92 (if print_errors then
93 let level =
94 if args.full_fidelity_errors_all then
95 ParserErrors.Maximum
96 else
97 ParserErrors.Typical
99 let hhvm_compat_mode =
100 if args.codegen then
101 ParserErrors.HHVMCompat
102 else
103 ParserErrors.NoCompat
105 let error_env =
106 ParserErrors.make_env
107 syntax_tree
108 ~level
109 ~hhvm_compat_mode
110 ~codegen:args.codegen
111 ~parser_options:popt
113 let errors = ParserErrors.parse_errors error_env in
114 List.iter (print_full_fidelity_error source_text) errors);
115 begin
116 let dump_needed = args.full_fidelity_ast_s_expr in
117 let lowered =
118 if dump_needed || print_errors then (
119 let env =
120 Full_fidelity_ast.make_env
121 ~codegen:args.codegen
122 ~php5_compat_mode:args.php5_compat_mode
123 ~elaborate_namespaces:args.elaborate_namespaces
124 ~include_line_comments:args.include_line_comments
125 ~keep_errors:(args.keep_errors || print_errors)
126 ~quick_mode:args.quick_mode
127 ~parser_options:popt
128 ~fail_open:args.fail_open
129 file
132 let (errors, res) =
133 Errors.do_ (fun () -> Full_fidelity_ast.from_file_with_legacy env)
135 if print_errors then print_ast_check_errors errors;
136 Some res
137 with
138 | e when print_errors ->
139 let err = Base.Exn.to_string e in
140 let fn = Relative_path.suffix file in
141 (* If we've already found a parsing error, it's okay for lowering to fail *)
142 if not (Errors.currently_has_errors ()) then
143 Printf.eprintf
144 "Warning, lowering failed for %s\n - error: %s\n"
146 err;
148 None
149 ) else
150 None
152 match lowered with
153 | Some res ->
154 if dump_needed then
155 let ast = res.Parser_return.ast in
156 let str = Nast.show_program ast in
157 Printf.printf "%s\n" str
158 | None -> ()
159 end;
160 (if args.full_fidelity_json_parse_tree then
161 let json =
162 SyntaxTree.parse_tree_to_json
163 ~ignore_missing:args.ignore_missing_json
164 syntax_tree
166 let str = Hh_json.json_to_string json ~pretty:args.pretty_print_json in
167 Printf.printf "%s\n" str);
168 (if args.full_fidelity_json then
169 let json =
170 SyntaxTree.to_json ~ignore_missing:args.ignore_missing_json syntax_tree
172 let str = Hh_json.json_to_string json ~pretty:args.pretty_print_json in
173 Printf.printf "%s\n" str);
174 (if args.full_fidelity_text_json then
175 let json = Full_fidelity_editable_syntax.to_json editable in
176 let str = Hh_json.json_to_string json in
177 Printf.printf "%s\n" str);
178 (if args.full_fidelity_dot then
179 let dot = Full_fidelity_editable_syntax.to_dot editable false in
180 Printf.printf "%s\n" dot);
181 if args.full_fidelity_dot_edges then
182 let dot = Full_fidelity_editable_syntax.to_dot editable true in
183 Printf.printf "%s\n" dot
185 let handle_file args filename =
186 if Path.file_exists (Path.make filename) then
187 handle_existing_file args filename
188 else
189 Printf.printf "File %s does not exist.\n" filename
191 let rec main args files =
192 (if args.schema then
193 let schema = Schema.schema_as_json () in
194 Printf.printf "%s\n" schema);
195 match files with
196 | [] -> ()
197 | file :: tail ->
198 Unix.handle_unix_error (handle_file args) file;
199 main args tail
201 let () =
202 let args = parse_args () in
203 EventLogger.init_fake ();
204 let handle = SharedMem.init ~num_workers:0 SharedMem.default_config in
205 ignore (handle : SharedMem.handle);
206 main args args.files