Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add global jsx pragma #7785

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/commands/commandUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
6 changes: 6 additions & 0 deletions src/commands/config/flowConfig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/commands/config/flowConfig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions src/common/options.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Expand Down
26 changes: 18 additions & 8 deletions src/parsing/parsing_service_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -632,15 +639,15 @@ 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
let master_mutator, worker_mutator = Parsing_heaps.Reparse_mutator.create transaction all_files in
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, _, _) ->
Expand All @@ -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 ()
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
2 changes: 2 additions & 0 deletions tests/jsx_pragma_option/.flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[options]
jsx.pragma=bar
10 changes: 10 additions & 0 deletions tests/jsx_pragma_option/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@flow

import { bar } from './jsx'


// ok
const Hello = <hello a="nice" />;

// error
const Bye = <a />;
5 changes: 5 additions & 0 deletions tests/jsx_pragma_option/jsx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//@flow

declare export var bar: {
(type: 'hello', props: {|a: string|}, children: any): {| hello: 'div' |}
}
24 changes: 24 additions & 0 deletions tests/jsx_pragma_option/jsx_pragma_option.exp
Original file line number Diff line number Diff line change
@@ -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 = <a />;
^^^^^ [3]

References:
index.js:10:14
10| const Bye = <a />;
^ [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