diff --git a/src/printer.js b/src/printer.js
index 9154b46c..e78ec971 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -600,13 +600,19 @@ function genericPrintNoParens(path, options, print) {
fields.push("properties");
- var i = 0;
var props = [];
+ let separatorParts = [];
fields.forEach(function(field) {
path.each(
function(childPath) {
+ props.push(concat(separatorParts));
props.push(group(print(childPath)));
+
+ separatorParts = [separator, line];
+ if (util.isNextLineEmpty(options.originalText, childPath.getValue())) {
+ separatorParts.push(hardline);
+ }
},
field
);
@@ -639,7 +645,7 @@ function genericPrintNoParens(path, options, print) {
options.tabWidth,
concat([
options.bracketSpacing ? line : softline,
- join(concat([separator, line]), props)
+ concat(props)
])
),
ifBreak(canHaveTrailingComma && options.trailingComma ? "," : ""),
diff --git a/src/util.js b/src/util.js
index 7b7c24e9..99c1585c 100644
--- a/src/util.js
+++ b/src/util.js
@@ -124,7 +124,7 @@ function skip(chars) {
const skipWhitespace = skip(/\s/);
const skipSpaces = skip(" \t");
-const skipToLineEnd = skip("; \t");
+const skipToLineEnd = skip(",; \t");
const skipEverythingButNewLine = skip(/[^\r\n]/);
function skipInlineComment(text, index) {
diff --git a/tests/flow/get-def/__snapshots__/jsfmt.spec.js.snap b/tests/flow/get-def/__snapshots__/jsfmt.spec.js.snap
index 6f847d18..dff1ec58 100644
--- a/tests/flow/get-def/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/get-def/__snapshots__/jsfmt.spec.js.snap
@@ -81,6 +81,7 @@ module.exports = {
iTakeAString: function(name: string): number {
return 42;
},
+
bar: function(): number {
return 42;
}
diff --git a/tests/flow/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap b/tests/flow/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap
index bdd2922b..b5830417 100644
--- a/tests/flow/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap
@@ -210,29 +210,35 @@ var obj = {
get goodGetterWithAnnotation(): number {
return 4;
},
+
set goodSetterNoAnnotation(x) {
z = x;
},
set goodSetterWithAnnotation(x: number) {
z = x;
},
+
get propWithMatchingGetterAndSetter(): number {
return 4;
},
set propWithMatchingGetterAndSetter(x: number) {},
+
// The getter and setter need not have the same type
get propWithSubtypingGetterAndSetter(): ?number {
return 4;
}, // OK
set propWithSubtypingGetterAndSetter(x: number) {},
+
set propWithSubtypingGetterAndSetterReordered(x: number) {}, // OK
get propWithSubtypingGetterAndSetterReordered(): ?number {
return 4;
},
+
get exampleOfOrderOfGetterAndSetter(): A {
return new A();
},
set exampleOfOrderOfGetterAndSetter(x: B) {},
+
set exampleOfOrderOfGetterAndSetterReordered(x: B) {},
get exampleOfOrderOfGetterAndSetterReordered(): A {
return new A();
diff --git a/tests/flow/missing_annotation/__snapshots__/jsfmt.spec.js.snap b/tests/flow/missing_annotation/__snapshots__/jsfmt.spec.js.snap
index 2803fc17..5483c51d 100644
--- a/tests/flow/missing_annotation/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/missing_annotation/__snapshots__/jsfmt.spec.js.snap
@@ -95,18 +95,21 @@ var Foo = {
// missing arg annotation
return arg;
},
+
b: function(arg) {
// missing arg annotation
return {
bar: arg
};
},
+
c: function(arg: string) {
// no return annotation required
return {
bar: arg
};
},
+
d: function(
arg: string
): {
@@ -116,6 +119,7 @@ var Foo = {
bar: arg
};
},
+
// return type annotation may be omitted, but if so, input positions on
// observed return type (e.g. param types in a function type) must come
// from annotations
@@ -125,6 +129,7 @@ var Foo = {
return x;
};
},
+
// ...if the return type is annotated explicitly, this is unnecessary
f: function(arg: string): (x: number) => number {
return function(x) {
@@ -136,10 +141,13 @@ var Foo = {
var Bar = {
a: Foo.a(\"Foo\"), // no annotation required
+
// object property types are inferred, so make sure that this doesn\'t cause
// us to also infer the parameter\'s type.
b: Foo.b(\"bar\"), // no annotation required
+
c: Foo.c(\"bar\"), // no annotation required
+
d: Foo.d(\"bar\") // no annotation required
};
diff --git a/tests/flow/more_react/__snapshots__/jsfmt.spec.js.snap b/tests/flow/more_react/__snapshots__/jsfmt.spec.js.snap
index 3a2682fd..e567f9ae 100644
--- a/tests/flow/more_react/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/more_react/__snapshots__/jsfmt.spec.js.snap
@@ -79,12 +79,15 @@ var App = React.createClass({
getDefaultProps: function(): { y: string } {
return { y: \"\" }; // infer props.y: string
},
+
getInitialState: function() {
return { z: 0 }; // infer state.z: number
},
+
handler: function() {
this.setState({ z: 42 }); // ok
},
+
render: function() {
var x = this.props.x;
var y = this.props.y;
diff --git a/tests/flow/new_react/__snapshots__/jsfmt.spec.js.snap b/tests/flow/new_react/__snapshots__/jsfmt.spec.js.snap
index 44c78378..ceee6a56 100644
--- a/tests/flow/new_react/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/new_react/__snapshots__/jsfmt.spec.js.snap
@@ -67,6 +67,7 @@ var FeedUFI = React.createClass({
);
},
+
render: function(): ?React.Element {
return ;
}
@@ -130,6 +131,7 @@ var UFILikeCount = React.createClass({
permalink: React.PropTypes.string,
feedback: React.PropTypes.object.isRequired
},
+
render: function(): ?React.Element {
return ;
}
@@ -337,22 +339,29 @@ var FooLegacy = React.createClass({
propTypes: {
x: React.PropTypes.number.isRequired
},
+
getDefaultProps(): DefaultProps {
return {};
},
+
statics: {
bar(): void {}
},
+
qux(): void {
var _: string = this.props.x;
},
+
getInitialState(): { y: string } {
return { y: \"\" };
},
+
setState(o: { y_: string }): void {},
+
componentDidMount(): void {
this.is_mounted = true;
},
+
componentWillReceiveProps(nextProps: Object, nextContext: any): void {
this.qux();
}
@@ -452,6 +461,7 @@ var C = React.createClass({
z: React.PropTypes.number
},
replaceProps(props: {}) {},
+
getDefaultProps(): { z: number } {
return { z: 0 };
},
@@ -558,9 +568,11 @@ var TestProps = React.createClass({
x: React.PropTypes.string,
z: React.PropTypes.number
},
+
getDefaultProps: function() {
return { x: \"\", y: 0 };
},
+
test: function() {
var a: number = this.props.x; // error
var b: string = this.props.y; // error
@@ -688,12 +700,14 @@ var TestProps = React.createClass({
object_rec: React.PropTypes.object.isRequired,
string: React.PropTypes.string,
string_rec: React.PropTypes.string.isRequired,
+
any: React.PropTypes.any,
any_rec: React.PropTypes.any.isRequired,
element: React.PropTypes.element,
element_rec: React.PropTypes.element.isRequired,
node: React.PropTypes.node,
node_rec: React.PropTypes.node.isRequired,
+
arrayOf: React.PropTypes.arrayOf(React.PropTypes.string),
arrayOf_rec: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
instanceOf: React.PropTypes.instanceOf(Object),
@@ -718,6 +732,7 @@ var TestProps = React.createClass({
foo: React.PropTypes.string,
bar: React.PropTypes.number
}).isRequired,
+
// And do something bad here
bad_one: React.PropTypes.imaginaryType,
bad_two: React.PropTypes.string.inRequired
@@ -840,6 +855,7 @@ var ReactClass = React.createClass({
getInitialState: function(): State {
return { bar: null };
},
+
render: function(): any {
// Any state access here seems to make state any
this.state;
@@ -919,6 +935,7 @@ var TestState = React.createClass({
x: \"\"
};
},
+
test: function() {
var a: number = this.state.x; // error
@@ -951,6 +968,7 @@ var C = React.createClass({
getInitialState: function() {
return { x: 0 };
},
+
render() {
this.setState({ y: 0 });
return {this.state.z}
;
diff --git a/tests/flow/overload/__snapshots__/jsfmt.spec.js.snap b/tests/flow/overload/__snapshots__/jsfmt.spec.js.snap
index 45809dd3..6782e926 100644
--- a/tests/flow/overload/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/overload/__snapshots__/jsfmt.spec.js.snap
@@ -65,6 +65,7 @@ var x4: number = \"\".split(/pattern/)[0];
declare class C {
foo(x: number): number,
foo(x: string): string,
+
bar(x: { a: number }): number,
bar(x: { a: string }): string
}
diff --git a/tests/flow/react/__snapshots__/jsfmt.spec.js.snap b/tests/flow/react/__snapshots__/jsfmt.spec.js.snap
index 9fbf4260..e3190c87 100644
--- a/tests/flow/react/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/react/__snapshots__/jsfmt.spec.js.snap
@@ -271,6 +271,7 @@ var React = React.createClass({
return \"Alice\";
}
},
+
render() {
// But this never errored
return ;
diff --git a/tests/flow/react_modules/__snapshots__/jsfmt.spec.js.snap b/tests/flow/react_modules/__snapshots__/jsfmt.spec.js.snap
index ba395957..b92ca222 100644
--- a/tests/flow/react_modules/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/react_modules/__snapshots__/jsfmt.spec.js.snap
@@ -34,6 +34,7 @@ var HelloLocal = React.createClass({
propTypes: {
name: React.PropTypes.string.isRequired
},
+
render: function(): React.Element<*> {
return {this.props.name}
;
}
@@ -77,6 +78,7 @@ var Hello = React.createClass({
propTypes: {
name: React.PropTypes.string.isRequired
},
+
render: function(): React.Element<*> {
return {this.props.name}
;
}
diff --git a/tests/flow/type-at-pos/__snapshots__/jsfmt.spec.js.snap b/tests/flow/type-at-pos/__snapshots__/jsfmt.spec.js.snap
index 84dd79aa..67f64998 100644
--- a/tests/flow/type-at-pos/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/type-at-pos/__snapshots__/jsfmt.spec.js.snap
@@ -33,6 +33,7 @@ export const X = {
returnsATuple: function(): [number, number] {
return [1, 2];
},
+
test: function() {
let [a, b] = this.returnsATuple();
}
diff --git a/tests/flow/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap b/tests/flow/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap
index b8d332ab..c373ecf9 100644
--- a/tests/flow/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/flow/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap
@@ -63,22 +63,29 @@ declare class Promise {
reject: (error?: any) => void
) => void
): void,
+
then(
onFulfill?: ?(value: R) => Promise | ?U,
onReject?: ?(error: any) => Promise | ?U
): Promise,
+
done(
onFulfill?: ?(value: R) => void,
onReject?: ?(error: any) => void
): void,
+
catch(onReject?: (error: any) => ?Promise | U): Promise,
+
static resolve(object?: Promise | T): Promise,
static reject(error?: any): Promise,
+
// Non-standard APIs
finally(onSettled?: ?(value: any) => Promise | U): Promise,
+
static cast(object?: T): Promise,
static all(promises: Array | T>): Promise>,
static race(promises: Array>): Promise,
+
static allObject(promisesByKey: T): Promise<{
[key: $Keys]: any
}>