Skip to content
This repository has been archived by the owner on May 24, 2019. It is now read-only.

Add --comment option #68

Closed
Closed
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
6 changes: 5 additions & 1 deletion flow-remove-types
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var usage = 'Usage: flow-remove-types [options] [sources] \n' +
' -x, --extensions File extensions to transform\n' +
' -o, --out-file The file path to write transformed file to\n' +
' -d, --out-dir The directory path to write transformed files within\n' +
' -C, --comment Transform flow types to flow Comment Types in output\n' +
' -a, --all Transform all files, not just those with a @flow comment\n' +
' -p, --pretty Remove flow types without replacing with spaces, \n' +
' producing prettier output but may require using source maps\n' +
Expand Down Expand Up @@ -71,6 +72,7 @@ var ignore = /node_modules/;
var extensions = [ '.js', '.mjs', '.jsx', '.flow', '.es6' ];
var outDir;
var outFile;
var commentTypes;
var all;
var pretty;
var sourceMaps;
Expand All @@ -94,6 +96,8 @@ while (i < process.argv.length) {
outFile = process.argv[i++];
} else if (arg === '-d' || arg === '--out-dir') {
outDir = process.argv[i++];
} else if (arg === '-C' || arg === '--comment') {
commentTypes = true;
} else if (arg === '-a' || arg === '--all') {
all = true;
} else if (arg === '-p' || arg === '--pretty') {
Expand Down Expand Up @@ -231,7 +235,7 @@ function btoa(str) {

function transformSource(content, filepath) {
try {
return flowRemoveTypes(content, { all: all, pretty: pretty });
return flowRemoveTypes(content, { all: all, pretty: pretty, commentTypes: commentTypes });
} catch (error) {
if (error.loc) {
var line = error.loc.line - 1;
Expand Down
34 changes: 29 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ var vlq = require('vlq');
* If true, removes types completely rather than replacing with spaces.
* This may require using source maps.
*
* - commentTypes: (default: false)
* If true, transforms types to Comment Types using shortform syntax.
*
* Returns an object with two methods:
*
* - .toString()
Expand All @@ -25,6 +28,7 @@ var vlq = require('vlq');
module.exports = function flowRemoveTypes(source, options) {
// Options
var all = Boolean(options && options.all);
var commentTypes = Boolean(options && options.commentTypes);
if (options && options.checkPragma) {
throw new Error(
'flow-remove-types: the "checkPragma" option has been replaced by "all".'
Expand Down Expand Up @@ -61,8 +65,8 @@ module.exports = function flowRemoveTypes(source, options) {
pretty: Boolean(options && options.pretty)
};

// Remove the flow pragma.
if (pragmaStart !== -1) {
// Remove the flow pragma. if not using Comment Types
if (!commentTypes && pragmaStart !== -1) {
var pragmaIdx = findTokenIndex(ast.tokens, pragmaStart);
var pragmaType = ast.tokens[pragmaIdx].type;
if (pragmaType === 'CommentLine' || pragmaType === 'CommentBlock') {
Expand All @@ -76,9 +80,14 @@ module.exports = function flowRemoveTypes(source, options) {
return resultPrinter(options, source, removedNodes);
}

var LINE_RX = /(\r\n?|\n|\u2028|\u2029)/;
// var NESTED_COMMENTS_RX = /\s*(\/\*(.|\s)*?\*\/|\s*\/\/.*\r?\n)\s*/g;
var NESTED_COMMENTS_RX = / *(\/\*.*?\*\/| *\/\/.*) */g;

function resultPrinter(options, source, removedNodes) {
// Options
var pretty = Boolean(options && options.pretty);
var commentTypes = Boolean(options && options.commentTypes);

return {
toString: function () {
Expand All @@ -94,7 +103,24 @@ function resultPrinter(options, source, removedNodes) {
var node = removedNodes[i];
result += source.slice(lastPos, node.start);
lastPos = node.end;
if (!pretty) {
if (commentTypes) {
// Remove nested comments with a regexp replace
var toComment = source.slice(node.start, node.end).replace(NESTED_COMMENTS_RX, ' ').replace(/\s+;/, ';');
if (!node.loc || node.loc.start.line === node.loc.end.line) {
// possibly use the shorter single ':' syntax
if (toComment && toComment[0] === ':') {
result += ' /*' + toComment + ' */ ';
} else {
result += '/*:: ' + toComment + ' */';
}
} else {
var toCommentLines = toComment.split(LINE_RX);
// TODO: detect file line endings scheme (\n or \r\n)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably resolve this TODO. I wouldn't want to merge this feature if it messes up Windows line endings.

toCommentLines.unshift('/*::\n');
toCommentLines.push('\n*/');
result += toCommentLines.join('');
}
} else if (!pretty) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if both --pretty and --comment are specified?

var toReplace = source.slice(node.start, node.end);
if (!node.loc || node.loc.start.line === node.loc.end.line) {
result += space(toReplace.length);
Expand All @@ -121,8 +147,6 @@ function resultPrinter(options, source, removedNodes) {
}
}

var LINE_RX = /(\r\n?|\n|\u2028|\u2029)/;

// A collection of methods for each AST type names which contain Flow types to
// be removed.
var removeFlowVisitor = {
Expand Down
12 changes: 11 additions & 1 deletion test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ echo "Test: flow-remove-types --pretty test/source.js"
DIFF=$(./flow-remove-types --pretty test/source.js | diff test/expected-pretty.js -);
if [ -n "$DIFF" ]; then echo "$DIFF"; exit 1; fi;

# Test expected source maps with --pretty --sourcemaps
# Test expected source maps with --pretty --sourcemaps --out-dir
echo "Test: flow-remove-types --pretty --sourcemaps test/source.js -d test/expected-with-maps"
TEST_DIR=$(cd $(dirname ${BASH_SOURCE[0]}) && pwd)
DIR=$(mktemp -d)
Expand All @@ -29,6 +29,16 @@ echo "Test: flow-remove-types --pretty --sourcemaps inline test/source.js"
DIFF=$(./flow-remove-types --pretty --sourcemaps inline test/source.js | diff test/expected-pretty-inlinemap.js -);
if [ -n "$DIFF" ]; then echo "$DIFF"; exit 1; fi;

# Test expected output with --comment option
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also add the new test cases to test-update.sh.

echo "Test: flow-remove-types --comment test/source.js"
DIFF=$(./flow-remove-types --comment test/source.js | diff test/expected-comments.js -);
if [ -n "$DIFF" ]; then echo "$DIFF"; exit 1; fi;

# Test expected output with --comment option
echo "Test: flow-remove-types --comment test/source-nested-comments.js"
DIFF=$(./flow-remove-types --comment test/source-nested-comments.js | diff test/expected-nested-comments.js -);
if [ -n "$DIFF" ]; then echo "$DIFF"; exit 1; fi;

# Test expected output with @flow outside of comments
echo "Test: flow-remove-types test/without-flow.js"
DIFF=$(./flow-remove-types test/without-flow.js | diff test/without-flow.js -);
Expand Down
168 changes: 168 additions & 0 deletions test/expected-comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/* @flow */

// Regular import
import {
Something,
/*:: type SomeType *//*:: , */
/*:: typeof SomeOtherThing */
} from 'some-module';

// Import types
/*:: import type { SomeType } from 'some-module'; */

// Typed function
async function test(x /*: Type */ , y /*.*/ /*:: ? */ /*.*/ , z /*.*/ /*:: ? */ /*.*/ /*: number */ = 123) /*: string */ {
// Typed expression
return await (x /*: any */ );
}

// Interface
/*::
interface Foo {
prop: any;

method(): mixed;
}
*/

// Exported interface
/*::
export interface IThing {
exported: true;
}
*/

// Interface extends
/*::
interface SillyFoo extends Foo {
silly: string;
}
*/

// Implements interface
class Bar extends Other /*:: implements */ /*.*/ /*:: Foo *//*:: , */ /*:: ISomething */ {
// Class Property with default value
answer /*: number */ = 42;

// Class Property
/*:: prop: any; */

method() /*: mixed */ {
return;
}
}

// Class expression implements interface
var SomeClass = class Baz /*:: implements */ /*:: Foo */ {
/*:: prop: any; */

method() /*: mixed */ {
return;
}
};

// Parametric class
class Wrapper/*:: <T> */ {
get() /*: T */ {
return this.value;
}

map/*:: <M> */() /*: Wrapper<M> */ {
// do something
}
}

// Extends Parametric class
class StringWrapper extends Wrapper/*:: <string> */ {
// ...
}

// Declare class
/*::
declare class Baz {
method(): mixed;
}
*/

// Declare funtion
/*:: declare function someFunc(): void; */

// Declare interface
/*::
declare interface ISomething {
answer: number;
}
*/

// Declare module
/*::
declare module 'fs' {
declare function readThing(path: string): string;
}
*/

// Declare type alias
/*::
declare type Location = {
lat: number,
lon: number
};
*/

// Declare variable
/*:: declare var SOME_CONST: string; */

// Type alias
/*:: type T = string; */

// Export type
/*:: export type { T }; */

// Regular export
export { Wrapper };

// Exported type alias
/*:: export type ONE = { one: number }; */

// Object with types within
var someObj = {
objMethod() /*: void */ {
// do nothing.
}
}

// Example from README
import SomeClass from 'some-module'
/*:: import type { SomeInterface } from 'some-module' */

export class MyClass/*:: <T> */ extends SomeClass /*:: implements */ /*:: SomeInterface */ {

/*:: value: T */

constructor(value /*: T */ ) {
this.value = value
}

get() /*: T */ {
return this.value
}

}

// Test async/await functions
async function asyncFunction/*:: <T> */(input /*: T */ ) /*: Promise<T> */ {
return await t;
}

// Test read-only data
/*::
export type TestReadOnly = {|
+readOnly: $ReadOnlyArray<>
|};
*/

// Test covariant type variant class with constaint and default.
export class TestClassWithDefault/*:: <+T: TestReadOnly = TestReadOnly> */ {

constructor() {}
}
Loading