Use arrow function when inputted that way for flow objects (#608)

Omg, after 10 unsuccessful tries, I finally managed to get it working! The deciding factor was a trick by @mroch <3

Fixes #310
master
Christopher Chedeau 2017-02-04 18:23:37 -08:00 committed by James Long
parent 8c66e44db1
commit 91087e1e84
9 changed files with 47 additions and 6 deletions

View File

@ -1377,9 +1377,15 @@ function genericPrintNoParens(path, options, print) {
namedTypes.ObjectTypeProperty.check(parent) ||
namedTypes.ObjectTypeCallProperty.check(parent) ||
namedTypes.DeclareFunction.check(path.getParentNode(2)));
var needsColon = isArrowFunctionTypeAnnotation &&
namedTypes.TypeAnnotation.check(parent);
if (isObjectTypePropertyAFunction(parent)) {
isArrowFunctionTypeAnnotation = true;
needsColon = true;
}
if (needsColon) {
parts.push(": ");
}
@ -1499,6 +1505,11 @@ function genericPrintNoParens(path, options, print) {
var isFunction = !n.variance &&
!n.optional &&
n.value.type === "FunctionTypeAnnotation";
if (isObjectTypePropertyAFunction(n)) {
isFunction = true;
}
return concat([
n.static ? "static " : "",
variance,
@ -2673,6 +2684,16 @@ function isLastStatement(path) {
return body && body[body.length - 1] === node;
}
// Hack to differentiate between the following two which have the same ast
// type T = { method: () => void };
// type T = { method(): void };
function isObjectTypePropertyAFunction(node) {
return node.type === "ObjectTypeProperty" &&
node.value.type === "FunctionTypeAnnotation" &&
!node.static &&
util.locStart(node.key) !== util.locStart(node.value);
}
function shouldPrintSameLine(node) {
const type = node.type;
return namedTypes.Literal.check(node) ||

View File

@ -38,7 +38,7 @@ exports.Foo = Foo;
// so you want to type Foo, by declaring it as a class
interface IFooPrototype {
m(): number
m: () => number
}
interface IFoo extends IFooPrototype {
static (): void,

View File

@ -129,7 +129,7 @@ function bar(f: () => void) {
bar(foo); // error, since \`this\` is used non-trivially in \`foo\`
function qux(o: { f(): void }) {
function qux(o: { f: () => void }) {
o.f(); // passing o as \`this\`
}

View File

@ -43,7 +43,7 @@ function foo(x: ?number) {
type Bar = {
parent: ?Bar,
doStuff(): void
doStuff: () => void
};
function bar0(x: Bar) {

View File

@ -151,13 +151,13 @@ function foo(x: $Tainted<string>, o: Object) {
// Error
o.f(x);
}
function foo1(x: $Tainted<string>, o: { f(y: $Tainted<string>): void }) {
function foo1(x: $Tainted<string>, o: { f: (y: $Tainted<string>) => void }) {
o.f(x);
}
function foo2(o1: Object, o2: { t: $Tainted<string> }) {
o1.f(o2.t);
}
function foo3<T>(x: $Tainted<T>, o: { f(y: $Tainted<T>): void }) {
function foo3<T>(x: $Tainted<T>, o: { f: (y: $Tainted<T>) => void }) {
o.f(x);
}
function f_foo1(x: $Tainted<string>, f: Function) {

View File

@ -57,7 +57,7 @@ import typeof A from \"./A.js\";
import type { Foo, Bar as Baz } from \"./A.js\";
type duck = {
quack(): string
quack: () => string
};
// These string types should confict with the imported types

View File

@ -0,0 +1,14 @@
exports[`test method.js 1`] = `
"type T = { method: () => void };
type T = { method(): void };
declare class X { method(): void }
declare function f(): void;
var f: () => void;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type T = { method: () => void };
type T = { method(): void };
declare class X { method(): void }
declare function f(): void;
var f: () => void;
"
`;

View File

@ -0,0 +1 @@
run_spec(__dirname);

View File

@ -0,0 +1,5 @@
type T = { method: () => void };
type T = { method(): void };
declare class X { method(): void }
declare function f(): void;
var f: () => void;