";
- List.iter (self#html_of_module_element b father) eles;
- bs b "
"
- | Some m ->
- let (html_file, _) = Naming.html_files m.m_name in
- bp b " ";
- List.iter (self#html_of_module_element b father) eles;
- bs b "
"
- | Some m ->
- let (html_file, _) = Naming.html_files m.m_name in
- bp b " \n\n";
- bs b " ";
- bs b " | \n\n";
- bs b "";
- in
- let print_field_comment = function
- | None -> ()
- | Some t ->
- bs b "";
- bs b ""
- in
- bs b
- (match t.ty_manifest, t.ty_kind with
- None, Type_abstract
- | None, Type_open -> "\n"
- | None, Type_variant _
- | None, Type_record _ -> "\n"
- | Some _, Type_abstract
- | Some _, Type_open -> "\n"
- | Some _, Type_variant _
- | Some _, Type_record _ -> "\n"
- );
- bp b "" (Naming.type_target t);
- bs b ((self#keyword "type")^" ");
- bs b (Name.simple t.ty_name);
- (match t.ty_parameters with [] -> () | _ -> bs b " ");
- self#html_of_type_expr_param_list b father t;
- bs b " ";
- let priv = t.ty_private = Asttypes.Private in
- (
- match t.ty_manifest with
- None -> ()
- | Some (Object_type fields) ->
- bs b "= ";
- if priv then bs b "private ";
- bs b "< ";
- bs b " \n" ;
- let print_one f =
- print_field_prefix () ;
- bp b "%s : "
- (Naming.objfield_target t f)
- f.of_name;
- self#html_of_type_expr b father f.of_type;
- bs b ";\n";
- print_field_comment f.of_text ;
- bs b "\n"
- in
- Odoc_html.print_concat b "\n" print_one fields;
- bs b " \n>\n";
- bs b " "
- | Some (Other typ) ->
- bs b "= ";
- if priv then bs b "private ";
- self#html_of_type_expr b father typ;
- bs b " "
- );
- (match t.ty_kind with
- Type_abstract -> bs b " "
- | Type_variant l ->
- bs b "= ";
- if priv then bs b "private ";
- bs b
- (
- match t.ty_manifest with
- None -> " "
- | Some _ -> ""
- );
- bs b "\n";
- let print_one constr =
- bs b "\n\n";
- bs b "";
- bs b (self#keyword "|");
- bs b " | \n\n";
- bs b "";
- bp b "%s"
- (Naming.const_target t constr)
- (self#constructor constr.vc_name);
- (
- match constr.vc_args, constr.vc_ret with
- Cstr_tuple [], None -> ()
- | l,None ->
- bs b (" " ^ (self#keyword "of") ^ " ");
- self#html_of_cstr_args ~par: false b father constr.vc_name " * " l;
- | Cstr_tuple [],Some r ->
- bs b (" " ^ (self#keyword ":") ^ " ");
- self#html_of_type_expr b father r;
- | l,Some r ->
- bs b (" " ^ (self#keyword ":") ^ " ");
- self#html_of_cstr_args ~par: false b father constr.vc_name " * " l;
- bs b (" " ^ (self#keyword "->") ^ " ");
- self#html_of_type_expr b father r;
- );
- bs b " | \n";
- (
- match constr.vc_text with
- None -> ()
- | Some t ->
- bs b "";
- bs b "";
- bs b "";
- );
- bs b "\n "
- in
- Odoc_html.print_concat b "\n" print_one l;
- bs b " \n"
- | Type_record l ->
- bs b "= ";
- if priv then bs b "private " ;
- bs b "{";
- bs b
- (
- match t.ty_manifest with
- None -> ""
- | Some _ -> ""
- );
- bs b "\n" ;
- let print_one r =
- bs b "\n\n";
- bs b " ";
- bs b " | \n\n";
- bs b "";
- if r.rf_mutable then bs b (self#keyword "mutable ") ;
- bp b "%s : "
- (Naming.recfield_target t r)
- r.rf_name;
- self#html_of_type_expr b father r.rf_type;
- bs b ", | \n";
- (
- match r.rf_text with
- None -> ()
- | Some t ->
- bs b "";
- bs b "";
- );
- bs b "\n "
- in
- Odoc_html.print_concat b "\n" print_one l;
- bs b " \n}\n"
- | Type_open ->
- bs b "= ..";
- bs b ""
- );
- bs b "\n";
- self#html_of_info b t.ty_info;
- bs b "\n"
-
- method html_of_class_kind b father ?cl kind =
- match kind with
- Class_structure (inh, eles) ->
- self#html_of_text b [Code "{"];
- (
- match cl with
- None ->
- bs b "\n";
- (
- match inh with
- [] -> ()
- | _ ->
- self#generate_inheritance_info b inh
- );
- List.iter (self#html_of_class_element b) eles;
- | Some cl ->
- let (html_file, _) = Naming.html_files cl.cl_name in
- bp b " .. " html_file
- );
- self#html_of_text b [Code "}"]
- | _ -> html#html_of_class_kind b father ?cl kind
-
-
- method html_of_class_type_kind b father ?ct kind =
- match kind with
- Class_signature (inh, eles) ->
- self#html_of_text b [Code "{"];
- (
- match ct with
- None ->
- bs b "\n";
- (
- match inh with
- [] -> ()
- | _ -> self#generate_inheritance_info b inh
- );
- List.iter (self#html_of_class_element b) eles
- | Some ct ->
- let (html_file, _) = Naming.html_files ct.clt_name in
- bp b " .. " html_file
- );
- self#html_of_text b [Code "}"]
- | _ -> html#html_of_class_type_kind b father ?ct kind
-
- end
-end
-
-let _ = Odoc_args.set_generator
- (Odoc_gen.Html (module Generator : Odoc_html.Html_generator))
- ;;*)
diff --git a/src/refmt/dune b/src/refmt/dune
index 70419f88c..818e26482 100644
--- a/src/refmt/dune
+++ b/src/refmt/dune
@@ -2,7 +2,7 @@
(name refmt_impl)
(public_name refmt)
(package reason)
- (libraries reason reason.cmdliner dune-build-info))
+ (libraries reason reason.cmdliner dune-build-info reason_version))
(rule
(targets git_commit.ml)
diff --git a/src/refmt/refmt_impl.ml b/src/refmt/refmt_impl.ml
index e8c257786..8b3403a9b 100644
--- a/src/refmt/refmt_impl.ml
+++ b/src/refmt/refmt_impl.ml
@@ -103,8 +103,7 @@ let refmt
let top_level_info =
let doc = "Reason's Parser & Pretty-printer" in
let man = [`S "DESCRIPTION"; `P "refmt lets you format Reason files, parse them, and convert them between OCaml syntax and Reason syntax."] in
-let version = "Reason " ^ Package.version ^ " @ " ^ Package.git_short_version
- in
+ let version = "Reason " ^ Reason_version.package_version_string in
Term.info "refmt" ~version ~doc ~man
let refmt_t =
diff --git a/src/vendored-omp/tools/dune b/src/vendored-omp/tools/dune
index 8122ac6b4..35301729a 100644
--- a/src/vendored-omp/tools/dune
+++ b/src/vendored-omp/tools/dune
@@ -18,7 +18,7 @@
(name gencopy)
(enabled_if
(and
- (>= %{ocaml_version} 5.0)))
+ (= %{ocaml_version} 5.0)))
(modules gencopy)
(libraries compiler-libs.common compiler-libs.bytecomp)
(flags :standard -w -3))
diff --git a/test/4.12/reasonComments-re.t/input.re b/test/4.12/reasonComments-re.t/input.re
index 6156f3c4a..24732b768 100644
--- a/test/4.12/reasonComments-re.t/input.re
+++ b/test/4.12/reasonComments-re.t/input.re
@@ -1,3 +1,4 @@
+[@reason.version 3.7];
3; /* - */
3 /*-*/
;
diff --git a/test/assert.t/run.t b/test/assert.t/run.t
index c0493bb26..e5346a04f 100644
--- a/test/assert.t/run.t
+++ b/test/assert.t/run.t
@@ -1,5 +1,6 @@
Format assertions
$ refmt ./input.re
+ [@reason.version 3.7];
switch (true) {
| true => ()
| false => assert(false)
diff --git a/test/basicStructures.t/run.t b/test/basicStructures.t/run.t
index cf6d3175e..6bc02a7ad 100644
--- a/test/basicStructures.t/run.t
+++ b/test/basicStructures.t/run.t
@@ -1,5 +1,6 @@
Format basicStructures
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let run = () => {
diff --git a/test/bigarray.t/run.t b/test/bigarray.t/run.t
index f464bba67..b6ef00371 100644
--- a/test/bigarray.t/run.t
+++ b/test/bigarray.t/run.t
@@ -1,5 +1,6 @@
Format bigarray
$ refmt ./input.re
+ [@reason.version 3.7];
my_big_array3.{
reallyLongStringThatWillDefinitelyBreakLine
};
diff --git a/test/bucklescript.t/run.t b/test/bucklescript.t/run.t
index 0c5b55994..9d7093a04 100644
--- a/test/bucklescript.t/run.t
+++ b/test/bucklescript.t/run.t
@@ -1,5 +1,6 @@
Format bucklescript
$ refmt ./input.re
+ [@reason.version 3.7];
bla #= 10;
bla #= Some(10);
diff --git a/test/class_types.t/run.t b/test/class_types.t/run.t
index 716dfe3cf..b684b756e 100644
--- a/test/class_types.t/run.t
+++ b/test/class_types.t/run.t
@@ -1,6 +1,7 @@
Format class and class type
$ refmt ./input.re
- class type _module ('provider_impl) = {};
+ [@reason.version 3.7];
+ class type _module('provider_impl) = {};
type t;
class type bzz = {
inherit _module(t);
diff --git a/test/class_types_3_dot_8.t/input.re b/test/class_types_3_dot_8.t/input.re
new file mode 100644
index 000000000..b0e6f439c
--- /dev/null
+++ b/test/class_types_3_dot_8.t/input.re
@@ -0,0 +1,43 @@
+/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
+
+[@reason.version 3.8];
+
+class type _module ('provider_impl) = {
+
+};
+type t;
+class type bzz = {
+ inherit _module(t)
+};
+
+class type s = { as 'a; };
+class type u = { as 'a;
+ constraint 'a = #s
+};
+
+/* https://github.com/facebook/reason/issues/2037 */
+class type xt = { as 'a };
+
+class x = {
+ as self
+};
+
+class type classWithNoArgType {
+ pub x : int;
+ pub y : int
+};
+
+class classWithNoArg {
+ pub x = 0;
+ pub y = 0
+};
+
+module M = {};
+class type v = {
+ open M;
+ as 'a;
+};
+
+class type w = {
+ open M;
+};
diff --git a/test/class_types_3_dot_8.t/run.t b/test/class_types_3_dot_8.t/run.t
new file mode 100644
index 000000000..bcc6ea546
--- /dev/null
+++ b/test/class_types_3_dot_8.t/run.t
@@ -0,0 +1,13 @@
+
+Format basic
+ $ refmt --print re ./input.re > ./formatted.re
+
+Type-check basics
+ $ ocamlc -c -pp 'refmt --print binary' -intf-suffix .rei -impl formatted.re
+
+Format the formatted file back
+ $ refmt --print re ./formatted.re > ./formatted_back.re
+
+Ensure idempotency: first format and second format are the same
+ $ diff formatted.re formatted_back.re
+
diff --git a/test/comments-ml.t/run.t b/test/comments-ml.t/run.t
index 19671337b..0b0b7503a 100644
--- a/test/comments-ml.t/run.t
+++ b/test/comments-ml.t/run.t
@@ -14,5 +14,5 @@ Format the formatted file back
Ensure idempotency: first format and second format are the same
$ diff formatted.re formatted_back.re
0a1
- >
+ > [@reason.version 3.7];
[1]
diff --git a/test/emptyFileComment.t/input.re b/test/emptyFileComment.t/input.re
index eb2b9c00d..39bd0f9c6 100644
--- a/test/emptyFileComment.t/input.re
+++ b/test/emptyFileComment.t/input.re
@@ -1 +1,2 @@
+[@reason.version 3.7];
// file with just a single line comment
diff --git a/test/emptyFileComment.t/run.t b/test/emptyFileComment.t/run.t
index 8fcb9da22..1323f7812 100644
--- a/test/emptyFileComment.t/run.t
+++ b/test/emptyFileComment.t/run.t
@@ -1,3 +1,4 @@
Format empty file comment
$ refmt ./input.re
+ [@reason.version 3.7];
// file with just a single line comment
diff --git a/test/escapesInStrings.t/input.re b/test/escapesInStrings.t/input.re
index 51e486fe1..f6efc72b8 100755
--- a/test/escapesInStrings.t/input.re
+++ b/test/escapesInStrings.t/input.re
@@ -1,3 +1,4 @@
+[@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
/*
diff --git a/test/escapesInStrings.t/run.t b/test/escapesInStrings.t/run.t
index e68366deb..25ff5fa08 100644
--- a/test/escapesInStrings.t/run.t
+++ b/test/escapesInStrings.t/run.t
@@ -1,5 +1,6 @@
Format escapes in strings
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
/*
diff --git a/test/extensions.t/input.re b/test/extensions.t/input.re
index 2bbeab3c2..b9df6a2d6 100644
--- a/test/extensions.t/input.re
+++ b/test/extensions.t/input.re
@@ -1,3 +1,5 @@
+[@reason.version 3.7];
+
/* Extension sugar */
[%extend open M];
diff --git a/test/extensions.t/run.t b/test/extensions.t/run.t
index 459bfe2e4..695e5632a 100644
--- a/test/extensions.t/run.t
+++ b/test/extensions.t/run.t
@@ -1,5 +1,7 @@
Format extensions
$ refmt ./input.re
+ [@reason.version 3.7];
+
/* Extension sugar */
[%extend open M];
diff --git a/test/externals.t/run.t b/test/externals.t/run.t
index 91a7a9cbf..722ebf41c 100644
--- a/test/externals.t/run.t
+++ b/test/externals.t/run.t
@@ -1,5 +1,6 @@
Format externals
$ refmt ./input.re
+ [@reason.version 3.7];
/**
* Tests external formatting.
*/
diff --git a/test/firstClassModules.t/run.t b/test/firstClassModules.t/run.t
index 4ad6da514..54428c20c 100644
--- a/test/firstClassModules.t/run.t
+++ b/test/firstClassModules.t/run.t
@@ -1,5 +1,6 @@
Format first class modules
$ refmt ./input.re
+ [@reason.version 3.7];
module Modifier = (
val Db.Hashtbl.create():
Db.Sig with type t = Mods.t
diff --git a/test/fixme.t/run.t b/test/fixme.t/run.t
index da9fcfbb5..3f2a2aa4f 100644
--- a/test/fixme.t/run.t
+++ b/test/fixme.t/run.t
@@ -1,5 +1,6 @@
Format fixme
$ refmt ./input.re
+ [@reason.version 3.7];
/**
* Problem: In thise example, the comment should have a space after it.
*/
diff --git a/test/functionInfix.t/run.t b/test/functionInfix.t/run.t
index 0b8c2baaa..0ed5e414a 100644
--- a/test/functionInfix.t/run.t
+++ b/test/functionInfix.t/run.t
@@ -1,5 +1,6 @@
Format function infix
$ refmt ./input.re
+ [@reason.version 3.7];
let entries = ref([]);
let all = ref(0);
diff --git a/test/general-syntax-re.t/run.t b/test/general-syntax-re.t/run.t
index 2d62820ef..b6c2d8fe4 100644
--- a/test/general-syntax-re.t/run.t
+++ b/test/general-syntax-re.t/run.t
@@ -1,5 +1,6 @@
Format general implementation syntax
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
[@autoFormat
diff --git a/test/general-syntax-rei.t/run.t b/test/general-syntax-rei.t/run.t
index 7a0ef630b..a04dbc184 100644
--- a/test/general-syntax-rei.t/run.t
+++ b/test/general-syntax-rei.t/run.t
@@ -1,5 +1,6 @@
Format general interface syntax
$ refmt ./input.rei
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
/**
diff --git a/test/generics.t/run.t b/test/generics.t/run.t
index ea1c09af0..559842e67 100644
--- a/test/generics.t/run.t
+++ b/test/generics.t/run.t
@@ -1,5 +1,6 @@
Format features from OCaml 4.03
$ refmt ./input.re
+ [@reason.version 3.7];
type t =
| A({a: int})
| B;
diff --git a/test/if.t/run.t b/test/if.t/run.t
index 933226dfb..fa6406f86 100644
--- a/test/if.t/run.t
+++ b/test/if.t/run.t
@@ -1,5 +1,6 @@
Format if statements
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let logTSuccess = self =>
diff --git a/test/infix.t/run.t b/test/infix.t/run.t
index 9725da45e..9aa86fcbb 100644
--- a/test/infix.t/run.t
+++ b/test/infix.t/run.t
@@ -1,5 +1,6 @@
Format infix operators
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
/* - A good way to test if formatting of infix operators groups precedences
diff --git a/test/jsx.t/run.t b/test/jsx.t/run.t
index 01f2990e9..94d6107d5 100644
--- a/test/jsx.t/run.t
+++ b/test/jsx.t/run.t
@@ -1,5 +1,6 @@
Format JSX
$ refmt ./input.re
+ [@reason.version 3.7];
let x =
{
diff --git a/test/modules_no_semi.t/run.t b/test/modules_no_semi.t/run.t
index 91dc96c67..bafbd890f 100644
--- a/test/modules_no_semi.t/run.t
+++ b/test/modules_no_semi.t/run.t
@@ -1,5 +1,6 @@
Format modules no semi
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let run = () => {
diff --git a/test/object.t/run.t b/test/object.t/run.t
index 2b1738d9b..2b8c75348 100644
--- a/test/object.t/run.t
+++ b/test/object.t/run.t
@@ -1,5 +1,6 @@
Format objects
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
type t = {.};
diff --git a/test/ocaml_identifiers.t/run.t b/test/ocaml_identifiers.t/run.t
index 1f52cfca3..528a1e839 100644
--- a/test/ocaml_identifiers.t/run.t
+++ b/test/ocaml_identifiers.t/run.t
@@ -1,5 +1,6 @@
Format OCaml identifiers file
$ refmt ./input.ml --print re
+ [@reason.version 3.7];
/* Type names (supported with PR#2342) */
module T = {
type pub_ = unit;
diff --git a/test/oo_3_dot_8.t/input.re b/test/oo_3_dot_8.t/input.re
new file mode 100644
index 000000000..1f036b5e2
--- /dev/null
+++ b/test/oo_3_dot_8.t/input.re
@@ -0,0 +1,435 @@
+/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
+
+[@reason.version 3.8];
+
+class virtual stack('a) (init) = {
+ /*
+ * The "as this" is implicit and will be formatted away.
+ */
+ val virtual dummy: unit;
+ val mutable v: list<'a> = init;
+ pub virtual implementMe: int => int;
+ pub pop =
+ switch (v) {
+ | [hd, ...tl] =>
+ v = tl;
+ Some(hd);
+ | [] => None
+ };
+ pub push = hd => {
+ v = [hd, ...v];
+ };
+ initializer {
+ print_string("initializing object");
+ };
+ pub explicitOverrideTest = a => {
+ a + 1;
+ };
+ pri explicitOverrideTest2 = a => {
+ a + 1;
+ };
+};
+
+let tmp = {
+ /**
+ * comment here.
+ */;
+ val x = 10
+};
+
+/**
+ * Comment on stackWithAttributes.
+ */
+[@thisShouldntBeFormattedAway]
+class virtual stackWithAttributes ('a) (init) = {
+ /* Before class */
+ /* The "as this" should not be formatted away because attributes. */
+ as [@thisShouldntBeFormattedAway] this;
+ /* Before floatting attribute */
+ [@floatingAttribute];
+ /* Virtual member */
+ [@itemAttr1] val virtual dummy: unit;
+ [@itemAttr2] val mutable v: list<'a> = init;
+ pub virtual implementMe: int => int;
+ pub pop =
+ switch (v) {
+ | [hd, ...tl] =>
+ v = tl;
+ Some(hd);
+ | [] => None
+ };
+ pub push = hd => {
+ v = [hd, ...v];
+ };
+ initializer {
+ print_string("initializing object");
+ };
+};
+
+class extendedStack ('a) (init) = {
+ inherit (class stack<'a>)(init);
+ val dummy = ();
+ pub implementMe = i => i;
+};
+
+class extendedStackAcknowledgeOverride
+ ('a)
+ (init) = {
+ inherit (class stack<'a>)(init);
+ val dummy = ();
+ pub implementMe = i => {
+ i + 1;
+ };
+ pub! explicitOverrideTest = a => {
+ a + 2;
+ };
+ pri! explicitOverrideTest2 = a => {
+ a + 2;
+ };
+};
+
+let inst = (new extendedStack)([1, 2]);
+
+/**
+ * Recursive classes.
+ */
+/*
+ * First recursive class.
+ */
+class firstRecursiveClass (init) = {
+ val v = init;
+}
+/*
+ * Second recursive class.
+ */
+and secondRecursiveClass (init) = {
+ val v = init;
+};
+
+/**
+ * For now, mostly for historic reasons, the syntax for type
+ * definitions/annotations on anonymous objects are different than
+ * "class_instance_type". That needn't be the case. The only challenge is that
+ * whatever we do, there is a slight challenge in avoiding conflicts with
+ * records. Clearly {x:int, y:int} will conflict. However, open object types in
+ * the form of {.. x:int, y:int} do not conflict. The only thing that must be
+ * resolved is closed object types and records. you could have a special token
+ * that means "closed". {. x: int, y:int}. If only closed object types would be
+ * optimized in the same way that records are, records could just be replaced
+ * with closed object types.
+ */
+/**
+ * Anonymous objects.
+ */
+
+type closedObj = {.};
+
+let (<..>) = (a, b) => a + b;
+let five = 2 <..> 3;
+
+type nestedObj = {. bar: {. a: int}};
+
+let (>>) = (a, b) => a > b;
+
+let bigger = 3 >> 2;
+
+type typeDefForClosedObj = {
+ .
+ x: int,
+ y: int,
+};
+type typeDefForOpenObj<'a> =
+ {
+ ..
+ x: int,
+ y: int,
+ } as 'a;
+let anonClosedObject: {
+ .
+ x: int,
+ y: int,
+} = {
+ pub x = {
+ 0;
+ };
+ pub y = {
+ 0;
+ }
+};
+
+let onlyHasX = {pub x = 0};
+let xs: list({. x: int}) = [
+ onlyHasX,
+ (anonClosedObject :> {. x: int}),
+];
+
+let constrainedAndCoerced = (
+ [anonClosedObject, anonClosedObject]:
+ list({
+ .
+ x: int,
+ y: int,
+ }) :>
+ list({. x: int})
+);
+
+/* If one day, unparenthesized type constraints are allowed on the RHS of a
+ * record value, we're going to have to be careful here because >} is parsed as
+ * a separate kind of token (for now). Any issues would likely be caught in the
+ * idempotent test case.
+ */
+let xs: ref({. x: int}) = {
+ contents: (anonClosedObject :> {. x: int}),
+};
+
+let coercedReturn = {
+ let tmp = anonClosedObject;
+ (tmp :> {. x: int});
+};
+
+let acceptsOpenAnonObjAsArg =
+ (
+ o: {
+ ..
+ x: int,
+ y: int,
+ },
+ ) =>
+ o#x + o#y;
+let acceptsClosedAnonObjAsArg =
+ (
+ o: {
+ .
+ x: int,
+ y: int,
+ },
+ ) =>
+ o#x + o#y;
+let res =
+ acceptsOpenAnonObjAsArg({
+ pub x = 0;
+ pub y = 10
+ });
+
+let res =
+ acceptsOpenAnonObjAsArg({
+ pub x = 0;
+ pub y = 10;
+ pub z = 10
+ });
+
+let res =
+ acceptsClosedAnonObjAsArg({
+ pub x = 0;
+ pub y = 10
+ });
+
+/* TODO: Unify class constructor return values with function return values */
+class myClassWithAnnotatedReturnType
+ (init)
+ : {
+ pub x: int;
+ pub y: int;
+ } = {
+ pub x: int = init;
+ pub y = init;
+};
+/**
+ * May include a trailing semi after type row.
+ */
+class myClassWithAnnotatedReturnType2
+ (init)
+ : {
+ pub x: int;
+ pub y: int;
+ } = {
+ pub x: int = init;
+ pub y = init;
+};
+
+/**
+ * May use equals sign, and may include colon if so.
+ */
+class myClassWithAnnotatedReturnType3
+ (init)
+ : {
+ pub x: int;
+ pub y: int;
+ } = {
+ pub x: int = init;
+ pub y: int = init;
+};
+
+/**
+ * The one difference between class_constructor_types and expression
+ * constraints, is that we have to include the prefix word "new" before the
+ * final component of any arrow. This isn't required when annotating just the
+ * return value with ": foo ".
+ * This is only to temporarily work around a parsing conflict. (Can't tell if
+ * in the final arrow component it should begin parsing a non_arrowed_core_type
+ * or a class_instance_type). A better solution, would be to include
+ * class_instance_type as *part* of core_type, but then fail when it is
+ * observed in the non-last arrow position, or if a non_arrowed_core_type
+ * appears in the last arrow position.
+ *
+ * class_instance_type wouldn't always fail if parsed as any "core type"
+ * everywhere else in the grammar.
+ *
+ * Once nuance to that would be making a parse rule for "type application", and
+ * deferring whether or not that becomes a Pcty_constr or a Ptyp_constr. (The
+ * same for type identifiers and extensions.)
+ */
+class myClassWithAnnotatedReturnType3_annotated_constructor:
+ (int) =>
+ {
+ pub x: int;
+ pub y: int;
+ } =
+ fun (init) => {
+ pub x: int = init;
+ pub y: int = init;
+ };
+
+class tupleClass ('a, 'b) (init: ('a, 'b)) = {
+ pub pr = init;
+};
+
+module HasTupleClasses: {
+ /**
+ * exportedClass.
+ */
+ class exportedClass:
+ (int) =>
+ {
+ pub x: int;
+ pub y: int;
+ };
+ /**
+ * anotherExportedClass.
+ */
+ class anotherExportedClass ('a, 'b):
+ (('a, 'b)) =>
+ {
+ pub pr: ('a, 'b);
+ };
+} = {
+ /**
+ * exportedClass.
+ */
+ class exportedClass =
+ class myClassWithAnnotatedReturnType3;
+
+ /**
+ * anotherExportedClass.
+ */
+ class anotherExportedClass ('a, 'b) =
+ class tupleClass<'a, 'b>;
+};
+
+class intTuples = class tupleClass;
+
+class intTuplesHardcoded =
+ (class tupleClass)((8, 8));
+
+/**
+ * Note that the inner tupleClass doesn't have the "class" prefix because
+ * they're not kinds of classes - they're types of *values*.
+ * The parens here shouldn't be required.
+ */
+class intTuplesTuples =
+ class tupleClass<
+ tupleClass,
+ tupleClass,
+ >;
+
+let x: tupleClass = {
+ pub pr = (10, 10)
+};
+
+let x: #tupleClass = x;
+
+let incrementMyClassInstance:
+ (int, #tupleClass) =>
+ #tupleClass =
+ (i, inst) => {
+ let (x, y) = inst#pr;
+ {pub pr = (x + i, y + i)};
+ };
+
+class myClassWithNoTypeParams = {};
+/**
+ * The #myClassWithNoTypeParams should be treated as "simple"
+ */
+type optionalMyClassSubtype<'a> =
+ option< #myClassWithNoTypeParams> as 'a;
+
+/**
+ * Remember, "class type" is really "class_instance_type" (which is the type of
+ * what is returned from the constructor).
+ *
+ * And when defining a class:
+ *
+ * addablePoint is the "class instance type" type generated in scope which is
+ * the closed object type of the return value of the constructor.
+ *
+ * #addablePoint is the extensible form of addablePoint (anything that
+ * adheres to the "interface.")
+ */
+class type addablePointClassType = {
+ pub x: int;
+ pub y: int;
+ pub add:
+ (
+ addablePointClassType,
+ addablePointClassType
+ ) =>
+ int;
+};
+
+/**
+ * Class constructor types can be annotated.
+ */
+class addablePoint:
+ (int) => addablePointClassType =
+ fun (init) => {
+ as self;
+ pub add =
+ (
+ one: addablePointClassType,
+ two: addablePointClassType,
+ ) =>
+ one#x + two#x + one#y + two#x;
+ pub x: int = init;
+ pub y = init;
+ };
+
+class addablePoint2:
+ (int) => addablePointClassType =
+ fun (init) => {
+ as self;
+ pub add =
+ (
+ one: addablePointClassType,
+ two: addablePointClassType,
+ ) =>
+ one#x + two#x + one#y + two#x;
+ pub x: int = init;
+ pub y = init;
+ };
+
+module type T = {
+ class virtual cl ('a): {}
+ and cl2: {};
+};
+
+let privacy = {pri x = c => 5 + c};
+
+module Js = {
+ type t<'a>;
+};
+
+/* supports trailing comma */
+type stream<'a> = {
+ .
+ "observer": ('a => unit) => unit,
+};
diff --git a/test/oo_3_dot_8.t/run.t b/test/oo_3_dot_8.t/run.t
new file mode 100644
index 000000000..bcc6ea546
--- /dev/null
+++ b/test/oo_3_dot_8.t/run.t
@@ -0,0 +1,13 @@
+
+Format basic
+ $ refmt --print re ./input.re > ./formatted.re
+
+Type-check basics
+ $ ocamlc -c -pp 'refmt --print binary' -intf-suffix .rei -impl formatted.re
+
+Format the formatted file back
+ $ refmt --print re ./formatted.re > ./formatted_back.re
+
+Ensure idempotency: first format and second format are the same
+ $ diff formatted.re formatted_back.re
+
diff --git a/test/pexpFun.t/run.t b/test/pexpFun.t/run.t
index ce4479c61..26cff22a5 100644
--- a/test/pexpFun.t/run.t
+++ b/test/pexpFun.t/run.t
@@ -1,5 +1,6 @@
Format function expressipns (pexpFun)
$ refmt ./input.re
+ [@reason.version 3.7];
let x =
switch (x) {
| Bar =>
diff --git a/test/pipeFirst.t/run.t b/test/pipeFirst.t/run.t
index 52e54c672..b88bb86c8 100644
--- a/test/pipeFirst.t/run.t
+++ b/test/pipeFirst.t/run.t
@@ -1,5 +1,6 @@
Format pipe first (->)
$ refmt ./input.re
+ [@reason.version 3.7];
foo->f->g->h;
bar->f->g->h;
diff --git a/test/polymorphism.t/run.t b/test/polymorphism.t/run.t
index e76a398a6..e269cc655 100644
--- a/test/polymorphism.t/run.t
+++ b/test/polymorphism.t/run.t
@@ -1,5 +1,6 @@
Format polymoprhism
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let run = () => {
diff --git a/test/print-width-env.t b/test/print-width-env.t
index e64e0c39d..0499af809 100644
--- a/test/print-width-env.t
+++ b/test/print-width-env.t
@@ -5,11 +5,13 @@ Create a file with a long line
Set the print width to 120 characters via env "REFMT_PRINT_WIDTH"
$ REFMT_PRINT_WIDTH=120 refmt test.re
+ [@reason.version 3.7];
let initialState =
uiStateFromValidated(~ownership=RemoteData.NotAsked, ~limits=initialLimits, SiteAuditSettings.default);
Set the print width to 80 characters via env "REFMT_PRINT_WIDTH"
$ REFMT_PRINT_WIDTH=80 refmt test.re
+ [@reason.version 3.7];
let initialState =
uiStateFromValidated(
~ownership=RemoteData.NotAsked,
diff --git a/test/sharpop.t/run.t b/test/sharpop.t/run.t
index 585a1f60a..8451552f5 100644
--- a/test/sharpop.t/run.t
+++ b/test/sharpop.t/run.t
@@ -1,5 +1,6 @@
Format sharp operator
$ refmt ./input.re
+ [@reason.version 3.7];
foo #= bar[0];
foo##bar[0] = 3;
diff --git a/test/singleLineCommentEof.t/input.re b/test/singleLineCommentEof.t/input.re
index 18f9b9683..6568d3029 100644
--- a/test/singleLineCommentEof.t/input.re
+++ b/test/singleLineCommentEof.t/input.re
@@ -1 +1,2 @@
+[@reason.version 3.7];
// let x = 1
diff --git a/test/singleLineCommentEof.t/run.t b/test/singleLineCommentEof.t/run.t
index 5fec6a04b..0b3d40575 100644
--- a/test/singleLineCommentEof.t/run.t
+++ b/test/singleLineCommentEof.t/run.t
@@ -1,3 +1,4 @@
Format single line comment at the end of the file
$ refmt ./input.re
+ [@reason.version 3.7];
// let x = 1
diff --git a/test/testUtils.t/run.t b/test/testUtils.t/run.t
index 57f189cb5..5b71e2af6 100644
--- a/test/testUtils.t/run.t
+++ b/test/testUtils.t/run.t
@@ -1,5 +1,6 @@
Format test utils
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let printSection = s => {
diff --git a/test/trailing.t/run.t b/test/trailing.t/run.t
index f28bd1786..fa78728d8 100644
--- a/test/trailing.t/run.t
+++ b/test/trailing.t/run.t
@@ -1,5 +1,7 @@
Format trailing
$ refmt ./input.re
+ [@reason.version 3.7];
+
let x = {"obj": obj};
let x = {"key": key, "keyTwo": keyTwo};
diff --git a/test/trailingSpaces.t/run.t b/test/trailingSpaces.t/run.t
index e72973b79..e3c1282d0 100644
--- a/test/trailingSpaces.t/run.t
+++ b/test/trailingSpaces.t/run.t
@@ -1,5 +1,6 @@
Format trailing spaces
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
module M =
diff --git a/test/typeDeclarations.t/run.t b/test/typeDeclarations.t/run.t
index baa4ea052..5971f7448 100644
--- a/test/typeDeclarations.t/run.t
+++ b/test/typeDeclarations.t/run.t
@@ -1,5 +1,6 @@
Format type declarations
$ refmt ./input.re
+ [@reason.version 3.7];
/* === test wrapping for arrows === */
type foo = option(int => int);
type foo = option((int, int) => int);
diff --git a/test/typeParameters.t/input.re b/test/typeParameters.t/input.re
index a4ca9c32c..08e084825 100644
--- a/test/typeParameters.t/input.re
+++ b/test/typeParameters.t/input.re
@@ -1,6 +1,7 @@
/**
* Testing type parameters.
*/
+[@reason.version 3.7];
type threeThings<'t> = ('t, 't, 't);
type listOf<'t> = list<'t>;
diff --git a/test/typeParameters_3_dot_8.t/input.re b/test/typeParameters_3_dot_8.t/input.re
new file mode 100644
index 000000000..c7d6710bf
--- /dev/null
+++ b/test/typeParameters_3_dot_8.t/input.re
@@ -0,0 +1,81 @@
+/**
+ * Testing type parameters.
+ */
+[@reason.version 3.8];
+
+type threeThings<'t> = ('t, 't, 't);
+type listOf<'t> = list<'t>;
+
+type underscoreParam<_> = Underscored;
+type underscoreParamCovariance<+_> = Underscored;
+type underscoreParamContravariance<-_> = Underscored;
+
+type tickParamCovariance<+'a> = Underscored;
+type tickParamContravariance<-'a> = Underscored;
+
+let x : option > = None;
+type myFunctionType<'a> = (list<('a, 'a)>, int => option >);
+let funcAnnoted = (~a: list=[0, 1, ], ()) => a;
+
+
+
+/**
+ * Syntax that would be likely to conflict with lexing parsing of < > syntax.
+ */
+
+let zero = 0;
+let isGreaterThanNegFive = zero > - 5;
+let isGreaterThanNegFive2 = zero > -5;
+let isGreaterThanNegFive3 = zero >(-5);
+
+let isGreaterThanEqNegFive = zero >= -5;
+let isGreaterThanEqNegFive2 = zero >= -5;
+let isGreaterThanEqNegFive3 = zero >=(-5);
+
+let (>>=) = (a, b) => a >= b;
+
+let isSuperGreaterThanEqNegFive = zero >>= - 5;
+let isSuperGreaterThanEqNegFive2 = zero >>= -5;
+let isSuperGreaterThanEqNegFive3 = zero >>= (-5);
+
+let jsx= (~children, ()) => 0;
+
+type t<'a> = 'a;
+let optionArg = (~arg:option>=?, ()) => arg;
+let optionArgList = (~arg:option>>=?, ()) => arg;
+let defaultJsxArg = (~arg:t(int)=, ()) => arg;
+let defaultFalse = (~arg:t=!true, ()) => arg;
+/* Doesn't work on master either let defaultTrue = (~arg:t= !!true) => arg; */
+
+/**
+ * Things likely to conflict or impact precedence.
+ */
+let neg=-1;
+let tru=!false;
+let x =
+ "arbitrary" === "example"
+ && "how long" >= "can you get"
+ && "seriously" <= "what is the line length";
+
+let z = 0;
+module Conss = {
+ let (>-) = (a, b) => a + b;
+ let four = 3 >- 1;
+ let two = 3 >- -1;
+ let four' = 3 >- - - 1;
+
+ let tr = 3 > - 1;
+ let tr' = 3 > - -1;
+ let tr'' = 3 > - - - 1;
+}
+
+module Idents = {
+ let (>-) = (a, b) => a + b;
+ let four = z >- z;
+ let two = z >- -z;
+ let four' = z >- - - z;
+
+ let tr = z > - z;
+ let tr' = z > - -z;
+ let tr'' = z > - - - z;
+}
diff --git a/test/typeParameters_3_dot_8.t/run.t b/test/typeParameters_3_dot_8.t/run.t
new file mode 100644
index 000000000..87812e8f9
--- /dev/null
+++ b/test/typeParameters_3_dot_8.t/run.t
@@ -0,0 +1,13 @@
+Format basic
+ $ refmt --print re ./input.re > ./formatted.re
+
+Type-check basics
+ $ ocamlc -c -pp 'refmt --print binary' -intf-suffix .rei -impl formatted.re
+
+Format the formatted file back
+ $ refmt --print re ./formatted.re > ./formatted_back.re
+
+Ensure idempotency: first format and second format are the same
+ $ diff formatted.re formatted_back.re
+
+
diff --git a/test/uncurried.t/run.t b/test/uncurried.t/run.t
index a4d347b3c..d6c22caa7 100644
--- a/test/uncurried.t/run.t
+++ b/test/uncurried.t/run.t
@@ -1,5 +1,6 @@
Format uncurried
$ refmt ./input.re
+ [@reason.version 3.7];
f(.);
[@attr]
diff --git a/test/variants.t/run.t b/test/variants.t/run.t
index e0e57e394..a3b13dca7 100644
--- a/test/variants.t/run.t
+++ b/test/variants.t/run.t
@@ -1,5 +1,6 @@
Format variants
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
module LocalModule = {
diff --git a/test/version.t b/test/version.t
index 444ddaf62..3e1fe1f99 100644
--- a/test/version.t
+++ b/test/version.t
@@ -1,3 +1,3 @@
Ensures refmt --version prints the right version
$ refmt --version | cut -d '@' -f 1
- Reason 3.8.2
+ Reason 3.7.0
diff --git a/test/whitespace-re.t/run.t b/test/whitespace-re.t/run.t
index 83cc6f0c1..3b52250b1 100644
--- a/test/whitespace-re.t/run.t
+++ b/test/whitespace-re.t/run.t
@@ -1,5 +1,6 @@
Format whitespace in .re files
$ refmt ./input.re
+ [@reason.version 3.7];
module Test = {
open Belt;
open React;
diff --git a/test/whitespace-rei.t/run.t b/test/whitespace-rei.t/run.t
index e4b4b700d..307d4e358 100644
--- a/test/whitespace-rei.t/run.t
+++ b/test/whitespace-rei.t/run.t
@@ -1,5 +1,6 @@
Format whitespace in .rei files
$ refmt ./input.rei
+ [@reason.version 3.7];
/** Interleave whitespace intelligently in signatures */
/* a */
diff --git a/test/wrapping-re.t/run.t b/test/wrapping-re.t/run.t
index c8823ac54..1207808ef 100644
--- a/test/wrapping-re.t/run.t
+++ b/test/wrapping-re.t/run.t
@@ -1,5 +1,6 @@
Format wrapping in .re files
$ refmt ./input.re
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
/* Run the formatting pretty printer with width 50 */
diff --git a/test/wrapping-rei.t/run.t b/test/wrapping-rei.t/run.t
index db8a10cd8..eb47e1330 100644
--- a/test/wrapping-rei.t/run.t
+++ b/test/wrapping-rei.t/run.t
@@ -1,5 +1,6 @@
Format wrapping in .rei files
$ refmt ./input.rei
+ [@reason.version 3.7];
/* Copyright (c) 2015-present, Facebook, Inc. All rights reserved. */
let named: (~a: int, ~b: int) => int;
|