-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: This adds a new command, `flow gen-flow-files path/to/file.js`, which generates the minimal `.js.flow` interface file that can be used for publishing compiled Flow source. Specifically: It generates only `import`, `declare`, and `declare export` statements in order to omit all the implementation text. Background: Currently the best practice for publishing Flow source is (roughly): 1. `cp src/foo.js dist/foo.js.flow` 2. `babel src/foo.js > dist/foo.js` This mostly works, but has a few downsides: 1. The published contents of `dist/*` are much larger than they need to be -- they contain a pre-compiled copy of all the original source. This is basically just crufty bytes that need to be downloaded every time the package is `npm install`-ed. 2. The published `.js.flow` files contain implementation details -- which are much more susceptible to breaking changes across Flow versions. While breaking changes across Flow version are still possible even in `declare` statements, this happens *far* less often. 3. We also want to re-use this type -> code codegen infrastructure to generate libdefs for flow-typed at some point. This particular diff is only about `.js.flow` files (i.e. no `declare module ...` statements) -- but that can be added on in a follow up diff. This diff includes a new `codegen.ml` file which exposes an API intended for generating code from various things (types for now, possibly ASTs at some point if that's useful/performant/worth the effort). It's minimal in terms of feature-set right now but we can expand/improve it later. I didn't use `type_printer.ml` because it only handles some types and many of the types it will print aren't actual code or easily composable with other bits of code. It's also used by lots of stuff that I didn't really want to investigate breaking changes for while building out this feature. At some point it probably makes sense to either improve `Type_printer` enough to subsume `Codegen` or the other way around. I suspect the `Codegen` is going to be easier to generalize, but we'll leave that for a later time to look into. Closes #2184 Reviewed By: gabelevi Differential Revision: D3663107 Pulled By: jeffmo fbshipit-source-id: 8f1147590e8bf48ebedb7b6ea5d1b720669c7518
- Loading branch information
Showing
43 changed files
with
1,470 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[ignore] | ||
|
||
[include] | ||
|
||
[libs] | ||
|
||
[options] | ||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// @flow | ||
|
||
export class Base<A, B, C> { | ||
}; | ||
|
||
export default class Child<A, B> extends Base<A, B, mixed> { | ||
p: number | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// @flow | ||
|
||
export default function<T: number, U: T, V: U> (a: V) { return a; } | ||
export function mono(a: number, b: {c: number}) { return a + b.c; }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// @flow | ||
|
||
export default 42; | ||
export const str = "asdf"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// @flow | ||
|
||
import {Child} from "./named_class_exports"; | ||
|
||
export const a: Child<number, string> = new Child(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// @flow | ||
|
||
export function fn(a: Array<number>) {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// @flow | ||
|
||
export var varBool = true; | ||
export var varBoolLiteral: true = true; | ||
export var varNum = 42; | ||
export var varNumLiteral: 42 = 42; | ||
export var varStr = "asdf"; | ||
export var varStrLiteral: "asdf" = "asdf"; | ||
|
||
export function f1(p: number) { | ||
return "asdf"; | ||
}; | ||
|
||
export function f2(p: 42): "asdf" { | ||
return "asdf"; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// @flow | ||
|
||
export class Base<A, B, C> { | ||
static baseStaticMethod(a: number, b: string) { return a; } | ||
static overriddenStaticMethod(a: {b: number, c: number}) { return a.b + a.c; } | ||
|
||
// Testing infinite type recursion | ||
baseInst: Base<number, string, mixed>; | ||
|
||
// Testing forward references | ||
childInst: Child<string, number>; | ||
|
||
baseMethod(a: number, b: string) { return a; } | ||
overriddenMethod(a: {b: number, c: number}) { return a.b + a.c; } | ||
}; | ||
|
||
export class Child<A, B> extends Base<A, B, mixed> { | ||
static overriddenStaticMethod(a: {b: number}) { return a.b; } | ||
|
||
notExported: NotExportedUsed<number>; | ||
overriddenMethod(a: {b: number}) { return a.b; } | ||
} | ||
|
||
class NotExportedUsed<T> { | ||
map<U>(f: (x:T) => U): NotExportedUsed<U> { | ||
return new NotExportedUsed(); | ||
}; | ||
} | ||
class NotExportedNotUsed {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// @flow | ||
|
||
export function mono(a: number, b: {c: number}) { return a + b.c; }; | ||
export function poly<T: number, U: T, V: U> (a: V) { return a; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// @flow | ||
|
||
export type T1 = number; | ||
export type T2<U, V> = Array<U>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// @flow | ||
|
||
export const constExport = 42; | ||
export let letExport = 43; | ||
export var varExport = 44; | ||
|
||
export type typeExport = number; | ||
|
||
type UnexportedT = string; | ||
export const unexportedAlias = ((0: any): UnexportedT); | ||
|
||
class C {} | ||
export const unexportedNominal = ((0: any): C); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export function addNum(a: number, b: number) { return a + b; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// @flow | ||
|
||
export var emptyObj = {}; | ||
|
||
export var singleProp = {p1: 42}; | ||
export var multiProp = {p1: 42, p2: 42}; | ||
export var nestedObject = {p1: {p2: 42}}; | ||
|
||
export var dict: {[key: string]: string} = {}; | ||
export var dictWithProps: { | ||
p1: string, | ||
[key: string]: number, | ||
} = {p1: "asdf"}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// @flow | ||
|
||
var obj: {b?: number} = {b: 42}; | ||
|
||
export {obj}; | ||
export var optNum = obj.b; | ||
export var optFunc = (p?: number) => p; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// @flow | ||
|
||
// $FlowFixMe | ||
export function fn() { return ('asdf': number); }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
/* @flow */ | ||
|
||
|
||
import {suite, test} from '../../tsrc/test/Tester'; | ||
|
||
export default suite(({addFile, flowCmd}) => [ | ||
test('named class exports', [ | ||
addFile('named_class_exports.js'), | ||
flowCmd(['gen-flow-files', 'named_class_exports.js']).stdout(` | ||
// @flow | ||
declare class Class0 { | ||
map<U>(f: (x: T) => U): Class0<U>; | ||
} | ||
declare export class Base<A, B, C> { | ||
static baseStaticMethod(a: number, b: string): number; | ||
static overriddenStaticMethod(a: {b: number, c: number}): number; | ||
baseInst: Base<number, string, mixed>; | ||
childInst: Child<string, number>; | ||
baseMethod(a: number, b: string): number; | ||
overriddenMethod(a: {b: number, c: number}): number; | ||
} | ||
declare export class Child<A, B> extends Base<A, B, mixed> { | ||
static overriddenStaticMethod(a: {b: number}): number; | ||
notExported: Class0<number>; | ||
overriddenMethod(a: {b: number}): number; | ||
} | ||
`) | ||
.stderr('') | ||
]), | ||
|
||
test('named variable exports', [ | ||
addFile('named_variable_exports.js'), | ||
flowCmd(['gen-flow-files', 'named_variable_exports.js']).stderr('').stdout(` | ||
// @flow | ||
declare class Class0 { | ||
} | ||
declare export var constExport: number; | ||
declare export var letExport: number; | ||
export type typeExport = number; | ||
declare export var unexportedAlias: string; | ||
declare export var unexportedNominal: Class0; | ||
declare export var varExport: number; | ||
`) | ||
]), | ||
|
||
test('named function exports', [ | ||
addFile('named_function_exports.js'), | ||
flowCmd(['gen-flow-files', 'named_function_exports.js']).stderr('').stdout(` | ||
// @flow | ||
declare export function mono(a: number, b: {c: number}): number; | ||
declare export function poly<T: number, U: T, V: U>(a: V): number; | ||
`) | ||
]), | ||
|
||
test('named type exports', [ | ||
addFile('named_type_exports.js'), | ||
flowCmd(['gen-flow-files', 'named_type_exports.js']).stderr('').stdout(` | ||
// @flow | ||
export type T1 = number; | ||
export type T2<U, V> = Array<U>; | ||
declare module.exports: {}; | ||
`), | ||
]), | ||
|
||
test('default class exports', [ | ||
addFile('default_class_export.js'), | ||
flowCmd(['gen-flow-files', 'default_class_export.js']).stderr('').stdout(` | ||
// @flow | ||
declare export class Base<A, B, C> { | ||
} | ||
declare export default class<A, B> extends Base<A, B, mixed> { | ||
p: number; | ||
} | ||
`), | ||
]), | ||
|
||
test('default variable exports', [ | ||
addFile('default_variable_exports.js'), | ||
flowCmd(['gen-flow-files', 'default_variable_exports.js']).stderr('').stdout(` | ||
// @flow | ||
declare export default number; | ||
declare export var str: string; | ||
`), | ||
]), | ||
|
||
test('default function exports', [ | ||
addFile('default_function_exports.js'), | ||
flowCmd(['gen-flow-files', 'default_function_exports.js']).stderr('').stdout(` | ||
// @flow | ||
declare export default function<T: number, U: T, V: U>(a: V): number; | ||
declare export function mono(a: number, b: {c: number}): number; | ||
`), | ||
]), | ||
|
||
test('non-@flow files', [ | ||
addFile('non_flow_file.js'), | ||
flowCmd(['gen-flow-files', '--strip-root', 'non_flow_file.js']).stderr('').stdout(` | ||
// This file does not have an @flow at the top! | ||
`), | ||
]), | ||
|
||
test('type errors halt and print to stderr', [ | ||
addFile('type_error.js'), | ||
flowCmd(['gen-flow-files', 'type_error.js']).stdout('').stderr(` | ||
type_error.js:3 | ||
3: export var a: string = 42; | ||
^^ number. This type is incompatible with | ||
3: export var a: string = 42; | ||
^^^^^^ string | ||
Found 1 error | ||
In order to generate a shadow file there must be no type errors! | ||
`) | ||
]), | ||
|
||
test('imported class types arent redefined', [ | ||
addFile('named_class_exports.js'), | ||
addFile('export_imported_type.js'), | ||
flowCmd(['gen-flow-files', 'export_imported_type.js']).stderr('').stdout(` | ||
// @flow | ||
import {Child} from "./named_class_exports"; | ||
declare export var a: Child<number, string>; | ||
`) | ||
]), | ||
|
||
test('builtin class types arent redefined', [ | ||
addFile('exports_builtins.js'), | ||
flowCmd(['gen-flow-files', 'exports_builtins.js']).stderr('').stdout(` | ||
// @flow | ||
declare export function fn(a: Array<number>): void; | ||
`) | ||
]), | ||
|
||
test('suppressed type errors get normalized', [ | ||
addFile('suppressions.js'), | ||
flowCmd(['gen-flow-files', 'suppressions.js']).stderr('').stdout(` | ||
// @flow | ||
declare export function fn(): number; | ||
`) | ||
]), | ||
|
||
test('literal types respect polarity', [ | ||
addFile('literal_types.js'), | ||
flowCmd(['gen-flow-files', 'literal_types.js']).stderr('').stdout(` | ||
// @flow | ||
declare export function f1(p: number): string; | ||
declare export function f2(p: 42): "asdf"; | ||
declare export var varBool: boolean; | ||
declare export var varBoolLiteral: true; | ||
declare export var varNum: number; | ||
declare export var varNumLiteral: 42; | ||
declare export var varStr: string; | ||
declare export var varStrLiteral: "asdf"; | ||
`) | ||
]), | ||
|
||
test('optional types', [ | ||
addFile('optional_types.js'), | ||
flowCmd(['gen-flow-files', 'optional_types.js']).stderr('').stdout(` | ||
// @flow | ||
declare export var obj: {b?: number}; | ||
declare export function optFunc(p?: number): void | number; | ||
declare export var optNum: void | number; | ||
`) | ||
]), | ||
|
||
test('object types', [ | ||
addFile('object_types.js'), | ||
flowCmd(['gen-flow-files', 'object_types.js']).stderr('').stdout(` | ||
// @flow | ||
declare export var dict: {[key: string]: string}; | ||
declare export var dictWithProps: {p1: string, [key: string]: number}; | ||
declare export var emptyObj: {}; | ||
declare export var multiProp: {p1: number, p2: number}; | ||
declare export var nestedObject: {p1: {p2: number}}; | ||
declare export var singleProp: {p1: number}; | ||
`) | ||
]), | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// @flow | ||
|
||
export var a: string = 42; |
Oops, something went wrong.