From 126d916f5ea9cc8adb2a7dd1425e75cd0cff2af1 Mon Sep 17 00:00:00 2001 From: andretshurotshka Date: Tue, 4 Jun 2019 12:34:23 +0500 Subject: [PATCH] Add global jsx pragma --- src/commands/commandUtils.ml | 1 + src/commands/config/flowConfig.ml | 6 +++++ src/commands/config/flowConfig.mli | 1 + src/common/options.ml | 2 ++ src/parsing/parsing_service_js.ml | 26 +++++++++++++------ tests/jsx_pragma_option/.flowconfig | 2 ++ tests/jsx_pragma_option/index.js | 10 +++++++ tests/jsx_pragma_option/jsx.js | 5 ++++ tests/jsx_pragma_option/jsx_pragma_option.exp | 24 +++++++++++++++++ 9 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 tests/jsx_pragma_option/.flowconfig create mode 100644 tests/jsx_pragma_option/index.js create mode 100644 tests/jsx_pragma_option/jsx.js create mode 100644 tests/jsx_pragma_option/jsx_pragma_option.exp diff --git a/src/commands/commandUtils.ml b/src/commands/commandUtils.ml index 11796e851c0..937e475c8af 100644 --- a/src/commands/commandUtils.ml +++ b/src/commands/commandUtils.ml @@ -1100,6 +1100,7 @@ let make_options ~flowconfig_name ~flowconfig ~lazy_mode ~root (options_flags: O opt_recursion_limit = FlowConfig.recursion_limit flowconfig; opt_max_files_checked_per_worker = FlowConfig.max_files_checked_per_worker flowconfig; opt_type_asserts = FlowConfig.type_asserts flowconfig; + opt_jsx_pragma = FlowConfig.jsx_pragma flowconfig; } let make_env flowconfig_name connect_flags root = diff --git a/src/commands/config/flowConfig.ml b/src/commands/config/flowConfig.ml index 475cdabd1da..afd6fa5da98 100644 --- a/src/commands/config/flowConfig.ml +++ b/src/commands/config/flowConfig.ml @@ -101,6 +101,7 @@ module Opts = struct types_first: bool; wait_for_recheck: bool; weak: bool; + jsx_pragma: string option; } let warn_on_unknown_opts (raw_opts, config) : (t * warning list, error) result = @@ -192,6 +193,7 @@ module Opts = struct types_first = false; wait_for_recheck = false; weak = false; + jsx_pragma = None; } let parse_lines : line list -> (raw_options, error) result = @@ -634,6 +636,9 @@ module Opts = struct "experimental.types_first.max_files_checked_per_worker", uint (fun opts v -> Ok { opts with max_files_checked_per_worker = v }); + + "jsx.pragma", + string (fun opts v -> Ok { opts with jsx_pragma = Some v }); ] let parse = @@ -1070,6 +1075,7 @@ let traces c = c.options.Opts.traces let trust_mode c = c.options.Opts.trust_mode let type_asserts c = c.options.Opts.type_asserts let types_first c = c.options.Opts.types_first +let jsx_pragma c = c.options.Opts.jsx_pragma let required_version c = c.version let wait_for_recheck c = c.options.Opts.wait_for_recheck let weak c = c.options.Opts.weak diff --git a/src/commands/config/flowConfig.mli b/src/commands/config/flowConfig.mli index 45a21a30355..8ade9b29af4 100644 --- a/src/commands/config/flowConfig.mli +++ b/src/commands/config/flowConfig.mli @@ -95,6 +95,7 @@ val traces: config -> int val trust_mode: config -> Options.trust_mode val type_asserts: config -> bool val types_first: config -> bool +val jsx_pragma: config -> string option val wait_for_recheck: config -> bool val weak: config -> bool diff --git a/src/common/options.ml b/src/common/options.ml index 6ff71845b17..05c19c05b04 100644 --- a/src/common/options.ml +++ b/src/common/options.ml @@ -117,6 +117,7 @@ type t = { opt_include_suppressions : bool; opt_trust_mode: trust_mode; opt_type_asserts: bool; + opt_jsx_pragma: string option; } let all opts = opts.opt_all @@ -182,6 +183,7 @@ let strict_mode opts = opts.opt_strict_mode let trust_mode opts = opts.opt_trust_mode let type_asserts opts = opts.opt_type_asserts +let jsx_pragma opts = opts.opt_jsx_pragma let lazy_mode_to_string lazy_mode = diff --git a/src/parsing/parsing_service_js.ml b/src/parsing/parsing_service_js.ml index 20c97ee2e7d..8f9fbf14761 100644 --- a/src/parsing/parsing_service_js.ml +++ b/src/parsing/parsing_service_js.ml @@ -472,7 +472,7 @@ let does_content_match_file_hash ~reader file content = * Add success/error info to passed accumulator. *) let reducer ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch - ~max_header_tokens ~noflow ~parse_unchanged + ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged parse_results file : results = (* It turns out that sometimes files appear and disappear very quickly. Just @@ -525,6 +525,13 @@ let reducer if noflow file then { info with Docblock.flow = Some Docblock.OptOut } else info in + let info = match jsx_pragma with + | Some jsx_pragma -> + let padding = (String.make 1 '\n') ^ (String.make 1 ' ') in + let (jsx_expr, _) = Parser_flow.jsx_pragma_expression (padding ^ jsx_pragma) (Some file) in + { info with Docblock.jsx = Some (Docblock.Jsx_pragma (jsx_pragma, jsx_expr)) } + | None -> info + in begin match (do_parse ~parse_options ~info content file) with | Parse_ok parse_ok -> let ast, file_sig = basic parse_ok in @@ -602,13 +609,13 @@ let next_of_filename_set ?(with_progress=false) workers filenames = else MultiWorkerLwt.next workers (FilenameSet.elements filenames) let parse ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch ~profile - ~max_header_tokens ~noflow ~parse_unchanged workers next + ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged workers next : results Lwt.t = let t = Unix.gettimeofday () in let reducer = reducer ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch - ~max_header_tokens ~noflow ~parse_unchanged + ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged in let%lwt results = MultiWorkerLwt.call workers @@ -632,7 +639,7 @@ let parse ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch ~profile Lwt.return results let reparse - ~transaction ~reader ~parse_options ~profile ~max_header_tokens ~noflow + ~transaction ~reader ~parse_options ~profile ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged ~with_progress ~workers ~modified:files ~deleted = (* save old parsing info for files *) let all_files = FilenameSet.union files deleted in @@ -640,7 +647,7 @@ let reparse let next = next_of_filename_set ?with_progress workers files in let%lwt results = parse ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch:false ~profile - ~max_header_tokens ~noflow ~parse_unchanged workers next + ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged workers next in let modified = results.parse_ok |> FilenameMap.keys |> FilenameSet.of_list in let modified = List.fold_left (fun acc (fail, _, _) -> @@ -664,6 +671,7 @@ let parse_with_defaults ?types_mode ?use_strict ~reader options workers next = let facebook_fbt = Options.facebook_fbt options in let arch = Options.arch options in let abstract_locations = options.Options.opt_abstract_locations in + let jsx_pragma = Options.jsx_pragma options in let parse_options = make_parse_options ~arch ~abstract_locations ~types_mode ~use_strict ~module_ref_prefix ~facebook_fbt () @@ -673,7 +681,7 @@ let parse_with_defaults ?types_mode ?use_strict ~reader options workers next = let worker_mutator = Parsing_heaps.Parse_mutator.create () in parse ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch:false - ~profile ~max_header_tokens ~noflow ~parse_unchanged workers next + ~profile ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged workers next let reparse_with_defaults ~transaction ~reader ?types_mode ?use_strict ?with_progress @@ -686,12 +694,13 @@ let reparse_with_defaults let facebook_fbt = Options.facebook_fbt options in let arch = Options.arch options in let abstract_locations = options.Options.opt_abstract_locations in + let jsx_pragma = Options.jsx_pragma options in let parse_options = make_parse_options ~arch ~abstract_locations ~types_mode ~use_strict ~module_ref_prefix ~facebook_fbt () in reparse - ~transaction ~reader ~parse_options ~profile ~max_header_tokens ~noflow + ~transaction ~reader ~parse_options ~profile ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged ~with_progress ~workers ~modified ~deleted (* ensure_parsed takes a set of files, finds the files which haven't been parsed, and parses them. @@ -730,6 +739,7 @@ let ensure_parsed ~reader options workers files = let facebook_fbt = Options.facebook_fbt options in let arch = Options.arch options in let abstract_locations = options.Options.opt_abstract_locations in + let jsx_pragma = Options.jsx_pragma options in let parse_options = make_parse_options ~types_mode ~use_strict ~module_ref_prefix ~facebook_fbt ~arch @@ -738,7 +748,7 @@ let ensure_parsed ~reader options workers files = let%lwt results = parse ~worker_mutator ~reader ~parse_options ~skip_hash_mismatch:true - ~profile ~max_header_tokens ~noflow ~parse_unchanged workers next + ~profile ~max_header_tokens ~noflow ~jsx_pragma ~parse_unchanged workers next in Lwt.return results.parse_hash_mismatch_skips diff --git a/tests/jsx_pragma_option/.flowconfig b/tests/jsx_pragma_option/.flowconfig new file mode 100644 index 00000000000..e3502af3b06 --- /dev/null +++ b/tests/jsx_pragma_option/.flowconfig @@ -0,0 +1,2 @@ +[options] +jsx.pragma=bar diff --git a/tests/jsx_pragma_option/index.js b/tests/jsx_pragma_option/index.js new file mode 100644 index 00000000000..529ad1e4079 --- /dev/null +++ b/tests/jsx_pragma_option/index.js @@ -0,0 +1,10 @@ +//@flow + +import { bar } from './jsx' + + +// ok +const Hello = ; + +// error +const Bye = ; diff --git a/tests/jsx_pragma_option/jsx.js b/tests/jsx_pragma_option/jsx.js new file mode 100644 index 00000000000..1d2762db23a --- /dev/null +++ b/tests/jsx_pragma_option/jsx.js @@ -0,0 +1,5 @@ +//@flow + +declare export var bar: { + (type: 'hello', props: {|a: string|}, children: any): {| hello: 'div' |} +} diff --git a/tests/jsx_pragma_option/jsx_pragma_option.exp b/tests/jsx_pragma_option/jsx_pragma_option.exp new file mode 100644 index 00000000000..cd43568ef97 --- /dev/null +++ b/tests/jsx_pragma_option/jsx_pragma_option.exp @@ -0,0 +1,24 @@ +Error --------------------------------------------------------------------------------------------------- index.js:10:13 + +Cannot create `a` element because: + - `a` [1] is incompatible with string literal `hello` [2]. + - inexact null [3] is incompatible with exact object type [4]. + + index.js:10:13 + 10| const Bye = ; + ^^^^^ [3] + +References: + index.js:10:14 + 10| const Bye = ; + ^ [1] + jsx.js:4:10 + 4| (type: 'hello', props: {|a: string|}, children: any): {| hello: 'div' |} + ^^^^^^^ [2] + jsx.js:4:26 + 4| (type: 'hello', props: {|a: string|}, children: any): {| hello: 'div' |} + ^^^^^^^^^^^^^ [4] + + + +Found 2 errors