├── .babelrc ├── .gitignore ├── README.md ├── babel-types-for-tracking-purposes ├── hooks └── pre-commit ├── package.json └── src ├── Printers.js ├── Tokens.js ├── __fixtures__ ├── babel │ ├── auto-indentation │ │ ├── hard-tab.js │ │ ├── soft-tab-2.js │ │ └── soft-tab-4.js │ ├── auto-string │ │ ├── double.js │ │ ├── jsx.js │ │ └── single.js │ ├── comments │ │ ├── 2-space-multi-comment-with-space.js │ │ ├── 2-space-multi-comment.js │ │ ├── block-line-comment-with-concise-format.js │ │ ├── block-line-comment-with-retainlines-option.js │ │ ├── block-line-comment.js │ │ ├── comment-only-with-space.js │ │ ├── comment-only.js │ │ ├── comment-statement-with-retainlines-option.js │ │ ├── computed-property-comments-2.js │ │ ├── computed-property-comments.js │ │ ├── do-while-line-comment.js │ │ ├── empty-line-comment.js │ │ ├── empty.js │ │ ├── function-block-line-comment.js │ │ ├── if-block-line-comment.js │ │ ├── if-empty-line-comment.js │ │ ├── if-line-comment.js │ │ ├── object_comments.js │ │ ├── return-no-argument.js │ │ ├── simple-a-lot-of-line-comment.js │ │ ├── simple-a-lot-of-multi-comment.js │ │ ├── simple-line-comment.js │ │ ├── simple-multi-comment.js │ │ ├── simple-statement-comment.js │ │ ├── try-block-line-comment.js │ │ ├── variable-declarator-line-comment.js │ │ ├── variable-declarator-multi-comment.js │ │ └── variable-declarator-trailing-comment.js │ ├── compact │ │ ├── assignment.js │ │ ├── binary-expressions.js │ │ ├── single-line-comment.js │ │ └── while.js │ ├── edgecase │ │ ├── bitwise-precedence.js │ │ ├── floating-point.js │ │ ├── for-in-no-in.js │ │ ├── for-loop-in.js │ │ ├── member-expression-numeric-literals.js │ │ ├── new-precedence.js │ │ ├── one-property-with-line-terminator.js │ │ ├── return-with-retainlines-and-compact-option.js │ │ ├── return-with-retainlines-option.js │ │ ├── unary-op.js │ │ └── variable-declaration.js │ ├── flow │ │ ├── array-types.js │ │ ├── boolean-literal-types.js │ │ ├── call-properties.js │ │ ├── declare-module.js │ │ ├── declare-statements.js │ │ ├── def-site-variance.js │ │ ├── interfaces-module-and-script.js │ │ ├── null-literal-types.js │ │ ├── number-literal-types.js │ │ ├── qualified-generic-type.js │ │ ├── string-literal-types.js │ │ ├── this-types.js │ │ ├── tuples.js │ │ ├── type-alias.js │ │ ├── type-annotations.js │ │ ├── type-parameters.js │ │ └── typecasts.js │ ├── harmony-edgecase │ │ ├── arrow-function.js │ │ ├── class-declaration.js │ │ ├── class-expression.js │ │ ├── computed-property.js │ │ ├── default-parameter.js │ │ ├── destructuring-assignment.js │ │ ├── export-default-declaration.js │ │ ├── exports.js │ │ ├── for-of-statement.js │ │ ├── import-with-default.js │ │ ├── imports.js │ │ ├── spread-element.js │ │ ├── templates-escape.js │ │ ├── templates-indentation.js │ │ ├── templates.js │ │ └── yield-precedence.js │ ├── minified │ │ ├── arrow-functions.js │ │ ├── block-statements.js │ │ ├── labeled-statement.js │ │ ├── literals.js │ │ ├── modules.js │ │ ├── new-expression.js │ │ └── no-semicolon.js │ ├── parentheses │ │ ├── arrow-function-object-body.js │ │ ├── arrow-function.js │ │ ├── assignment-expression.js │ │ ├── await-expression.js │ │ ├── expression.js │ │ ├── object.js │ │ ├── sequence-expressions.js │ │ ├── terminator-break.js │ │ ├── unary-arrow-function.js │ │ └── yield-expression.js │ └── types │ │ ├── ArrayExpression-ArrayPattern.js │ │ ├── ArrowFunctionExpression.js │ │ ├── AssignmentExpression-BinaryExpression-LogicalExpression.js │ │ ├── AwaitExpression.js │ │ ├── BindExpression.js │ │ ├── BlockStatement.js │ │ ├── BreakStatement.js │ │ ├── CallExpression.js │ │ ├── ClassBody-MethodDefinition.js │ │ ├── ClassDeclaration.js │ │ ├── ClassExpression.js │ │ ├── ConditionalExpression.js │ │ ├── ContinueStatement.js │ │ ├── DebuggerStatement.js │ │ ├── Decorator.js │ │ ├── DoWhileStatement.js │ │ ├── EmptyStatement.js │ │ ├── ExportDefaultDeclaration-ExportSpecifier-ExportNamedDeclaration.js │ │ ├── ForInStatement.js │ │ ├── ForOfStatement.js │ │ ├── ForStatement.js │ │ ├── FunctionDeclaration-FunctionExpression.js │ │ ├── Identifier.js │ │ ├── IfStatement.js │ │ ├── ImportDeclaration-ImportSpecifier-ImportNamespaceSpecifier.js │ │ ├── LabeledStatement.js │ │ ├── Literal.js │ │ ├── MemberExpression.js │ │ ├── NewExpression.js │ │ ├── ObjectExpression-ObjectPattern-Property.js │ │ ├── ReturnStatement.js │ │ ├── SequenceExpression.js │ │ ├── SpreadElement-SpreadProperty.js │ │ ├── SwitchStatement-SwitchCase.js │ │ ├── TemplateLiteral-TaggedTemplateExpression-TemplateElement.js │ │ ├── ThisExpression.js │ │ ├── ThrowStatement.js │ │ ├── TryStatement-CatchClause.js │ │ ├── UnaryExpression.js │ │ ├── UpdateExpression.js │ │ ├── VariableDeclaration-VariableDeclarator.js │ │ ├── WhileStatement.js │ │ ├── WithStatement.js │ │ ├── XJSAttribute.js │ │ ├── XJSElement-XJSOpeningElement-XJSClosingElement-XJSIdentifier.js │ │ ├── XJSEmptyExpression.js │ │ ├── XJSExpressionContainer.js │ │ ├── XJSMemberExpression.js │ │ ├── XJSNamespacedName.js │ │ ├── XJSSpreadAttribute.js │ │ └── YieldExpression.js ├── debug │ └── foo └── old │ ├── basics │ ├── simple-scope-breaking │ ├── variable-declarations │ └── works │ ├── comments │ ├── simple-block-comment │ └── simple-comment │ ├── formatting │ ├── binary_expression_chains │ ├── breaks_function_calls │ ├── complex_conditionals │ └── logical_expression_chains │ ├── integration │ ├── code_01 │ ├── code_02 │ └── flux_reduce_store │ └── literals │ ├── changes-quotes │ ├── large-numbers │ └── string-escapes ├── __tests__ ├── __snapshots__ │ ├── fjs_babel-test.js.snap │ ├── fjs_debug-test.js.snap │ └── fjs_old-test.js.snap ├── fjs_babel-test.js ├── fjs_debug-test.js ├── fjs_old-test.js ├── missing_printers-test.js └── tokens_spelling-test.js ├── applyRules.js ├── fjs.js ├── getGlobalContext.js ├── getMiddleware.js ├── getPrinters.js ├── getRules.js ├── print.js ├── printers ├── classes.js ├── comments.js ├── expressions.js ├── flow.js ├── functions.js ├── importExport.js ├── jsx.js ├── literals.js ├── misc.js ├── object.js ├── obsolete.js ├── patterns.js └── statements.js ├── regex.js ├── testFixtures.js ├── types.js └── utils.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": [ 4 | "syntax-async-functions", 5 | "syntax-flow", 6 | "syntax-jsx", 7 | "syntax-object-rest-spread", 8 | "syntax-trailing-function-commas", 9 | "transform-flow-strip-types", 10 | "transform-object-rest-spread", 11 | "transform-react-jsx", 12 | "transform-regenerator", 13 | "transform-runtime" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FJS 2 | 3 | Don't use this it's unsupported, use https://github.com/prettier/prettier instead, cheers! 4 | -------------------------------------------------------------------------------- /babel-types-for-tracking-purposes: -------------------------------------------------------------------------------- 1 | 2 | declare class BabelNodeCatchClause extends BabelNode { 3 | type: "CatchClause"; 4 | param: BabelNodeIdentifier; 5 | body: BabelNodeBlockStatement; 6 | } 7 | 8 | declare class BabelNodeDoWhileStatement extends BabelNode { 9 | type: "DoWhileStatement"; 10 | test: BabelNodeExpression; 11 | body: BabelNodeStatement; 12 | } 13 | 14 | declare class BabelNodeForInStatement extends BabelNode { 15 | type: "ForInStatement"; 16 | left: BabelNodeVariableDeclaration | BabelNodeLVal; 17 | right: BabelNodeExpression; 18 | body: BabelNodeStatement; 19 | } 20 | 21 | declare class BabelNodeForStatement extends BabelNode { 22 | type: "ForStatement"; 23 | init?: ?BabelNodeVariableDeclaration | BabelNodeExpression; 24 | test?: ?BabelNodeExpression; 25 | update?: ?BabelNodeExpression; 26 | body: BabelNodeStatement; 27 | } 28 | 29 | declare class BabelNodeFunctionDeclaration extends BabelNode { 30 | type: "FunctionDeclaration"; 31 | id: BabelNodeIdentifier; 32 | params: any; 33 | body: BabelNodeBlockStatement; 34 | generator?: boolean; 35 | async?: boolean; 36 | returnType: any; 37 | typeParameters: any; 38 | } 39 | 40 | declare class BabelNodeFunctionExpression extends BabelNode { 41 | type: "FunctionExpression"; 42 | id?: ?BabelNodeIdentifier; 43 | params: any; 44 | body: BabelNodeBlockStatement; 45 | generator?: boolean; 46 | async?: boolean; 47 | returnType: any; 48 | typeParameters: any; 49 | } 50 | 51 | declare class BabelNodeIfStatement extends BabelNode { 52 | type: "IfStatement"; 53 | test: BabelNodeExpression; 54 | consequent: BabelNodeStatement; 55 | alternate?: ?BabelNodeStatement; 56 | } 57 | 58 | declare class BabelNodeLogicalExpression extends BabelNode { 59 | type: "LogicalExpression"; 60 | operator: "||" | "&&"; 61 | left: BabelNodeExpression; 62 | right: BabelNodeExpression; 63 | } 64 | 65 | declare class BabelNodeNewExpression extends BabelNode { 66 | type: "NewExpression"; 67 | callee: BabelNodeExpression; 68 | arguments: any; 69 | } 70 | 71 | declare class BabelNodeObjectExpression extends BabelNode { 72 | type: "ObjectExpression"; 73 | properties: any; 74 | } 75 | 76 | declare class BabelNodeObjectMethod extends BabelNode { 77 | type: "ObjectMethod"; 78 | kind?: any; 79 | computed?: boolean; 80 | key: any; 81 | decorators: any; 82 | body: BabelNodeBlockStatement; 83 | generator?: boolean; 84 | async?: boolean; 85 | params: any; 86 | returnType: any; 87 | typeParameters: any; 88 | } 89 | 90 | declare class BabelNodeObjectProperty extends BabelNode { 91 | type: "ObjectProperty"; 92 | computed?: boolean; 93 | key: any; 94 | value: BabelNodeExpression; 95 | shorthand?: boolean; 96 | decorators?: any; 97 | } 98 | 99 | declare class BabelNodeRestElement extends BabelNode { 100 | type: "RestElement"; 101 | argument: BabelNodeLVal; 102 | typeAnnotation: any; 103 | } 104 | 105 | declare class BabelNodeReturnStatement extends BabelNode { 106 | type: "ReturnStatement"; 107 | argument?: ?BabelNodeExpression; 108 | } 109 | 110 | declare class BabelNodeSequenceExpression extends BabelNode { 111 | type: "SequenceExpression"; 112 | expressions: any; 113 | } 114 | 115 | declare class BabelNodeSwitchCase extends BabelNode { 116 | type: "SwitchCase"; 117 | test?: ?BabelNodeExpression; 118 | consequent: any; 119 | } 120 | 121 | declare class BabelNodeSwitchStatement extends BabelNode { 122 | type: "SwitchStatement"; 123 | discriminant: BabelNodeExpression; 124 | cases: any; 125 | } 126 | 127 | declare class BabelNodeThisExpression extends BabelNode { 128 | type: "ThisExpression"; 129 | } 130 | 131 | declare class BabelNodeThrowStatement extends BabelNode { 132 | type: "ThrowStatement"; 133 | argument: BabelNodeExpression; 134 | } 135 | 136 | declare class BabelNodeTryStatement extends BabelNode { 137 | type: "TryStatement"; 138 | body: BabelNodeBlockStatement; 139 | handler?: any; 140 | finalizer?: ?BabelNodeBlockStatement; 141 | block: any; 142 | } 143 | 144 | declare class BabelNodeUpdateExpression extends BabelNode { 145 | type: "UpdateExpression"; 146 | prefix?: boolean; 147 | argument: BabelNodeExpression; 148 | operator: "++" | "--"; 149 | } 150 | 151 | declare class BabelNodeWhileStatement extends BabelNode { 152 | type: "WhileStatement"; 153 | test: BabelNodeExpression; 154 | body: BabelNodeBlockStatement | BabelNodeStatement; 155 | } 156 | 157 | declare class BabelNodeWithStatement extends BabelNode { 158 | type: "WithStatement"; 159 | object: any; 160 | body: BabelNodeBlockStatement | BabelNodeStatement; 161 | } 162 | 163 | declare class BabelNodeArrayPattern extends BabelNode { 164 | type: "ArrayPattern"; 165 | elements: any; 166 | typeAnnotation: any; 167 | } 168 | 169 | declare class BabelNodeArrowFunctionExpression extends BabelNode { 170 | type: "ArrowFunctionExpression"; 171 | params: any; 172 | body: BabelNodeBlockStatement | BabelNodeExpression; 173 | async?: boolean; 174 | returnType: any; 175 | } 176 | 177 | declare class BabelNodeClassDeclaration extends BabelNode { 178 | type: "ClassDeclaration"; 179 | id: BabelNodeIdentifier; 180 | body: BabelNodeClassBody; 181 | superClass?: ?BabelNodeExpression; 182 | decorators: any; 183 | mixins: any; 184 | typeParameters: any; 185 | superTypeParameters: any; 186 | } 187 | 188 | declare class BabelNodeClassExpression extends BabelNode { 189 | type: "ClassExpression"; 190 | id?: ?BabelNodeIdentifier; 191 | body: BabelNodeClassBody; 192 | superClass?: ?BabelNodeExpression; 193 | decorators: any; 194 | mixins: any; 195 | typeParameters: any; 196 | superTypeParameters: any; 197 | } 198 | 199 | declare class BabelNodeExportAllDeclaration extends BabelNode { 200 | type: "ExportAllDeclaration"; 201 | source: BabelNodeStringLiteral; 202 | } 203 | 204 | declare class BabelNodeExportDefaultDeclaration extends BabelNode { 205 | type: "ExportDefaultDeclaration"; 206 | declaration: BabelNodeFunctionDeclaration | BabelNodeClassDeclaration | BabelNodeExpression; 207 | } 208 | 209 | declare class BabelNodeExportNamedDeclaration extends BabelNode { 210 | type: "ExportNamedDeclaration"; 211 | declaration?: ?BabelNodeDeclaration; 212 | specifiers: any; 213 | source?: ?BabelNodeStringLiteral; 214 | } 215 | 216 | declare class BabelNodeExportSpecifier extends BabelNode { 217 | type: "ExportSpecifier"; 218 | local: BabelNodeIdentifier; 219 | imported: BabelNodeIdentifier; 220 | exported: any; 221 | } 222 | 223 | declare class BabelNodeForOfStatement extends BabelNode { 224 | type: "ForOfStatement"; 225 | left: BabelNodeVariableDeclaration | BabelNodeLVal; 226 | right: BabelNodeExpression; 227 | body: BabelNodeStatement; 228 | } 229 | 230 | declare class BabelNodeImportDeclaration extends BabelNode { 231 | type: "ImportDeclaration"; 232 | specifiers: any; 233 | source: BabelNodeStringLiteral; 234 | } 235 | 236 | declare class BabelNodeImportDefaultSpecifier extends BabelNode { 237 | type: "ImportDefaultSpecifier"; 238 | local: BabelNodeIdentifier; 239 | } 240 | 241 | declare class BabelNodeImportNamespaceSpecifier extends BabelNode { 242 | type: "ImportNamespaceSpecifier"; 243 | local: BabelNodeIdentifier; 244 | } 245 | 246 | declare class BabelNodeImportSpecifier extends BabelNode { 247 | type: "ImportSpecifier"; 248 | local: BabelNodeIdentifier; 249 | imported: BabelNodeIdentifier; 250 | } 251 | 252 | declare class BabelNodeMetaProperty extends BabelNode { 253 | type: "MetaProperty"; 254 | meta: string; 255 | property: string; 256 | } 257 | 258 | declare class BabelNodeClassMethod extends BabelNode { 259 | type: "ClassMethod"; 260 | kind?: any; 261 | computed?: boolean; 262 | key: any; 263 | params: any; 264 | body: BabelNodeBlockStatement; 265 | generator?: boolean; 266 | async?: boolean; 267 | decorators: any; 268 | returnType: any; 269 | typeParameters: any; 270 | } 271 | 272 | declare class BabelNodeObjectPattern extends BabelNode { 273 | type: "ObjectPattern"; 274 | properties: any; 275 | typeAnnotation: any; 276 | } 277 | 278 | declare class BabelNodeSpreadElement extends BabelNode { 279 | type: "SpreadElement"; 280 | argument: BabelNodeExpression; 281 | } 282 | 283 | declare class BabelNodeTaggedTemplateExpression extends BabelNode { 284 | type: "TaggedTemplateExpression"; 285 | tag: BabelNodeExpression; 286 | quasi: BabelNodeTemplateLiteral; 287 | } 288 | 289 | declare class BabelNodeTemplateElement extends BabelNode { 290 | type: "TemplateElement"; 291 | value: any; 292 | tail?: boolean; 293 | } 294 | 295 | declare class BabelNodeTemplateLiteral extends BabelNode { 296 | type: "TemplateLiteral"; 297 | quasis: any; 298 | expressions: any; 299 | } 300 | 301 | declare class BabelNodeYieldExpression extends BabelNode { 302 | type: "YieldExpression"; 303 | delegate?: boolean; 304 | argument?: ?BabelNodeExpression; 305 | } 306 | 307 | declare class BabelNodeClassImplements extends BabelNode { 308 | type: "ClassImplements"; 309 | id: any; 310 | typeParameters: any; 311 | } 312 | 313 | declare class BabelNodeClassProperty extends BabelNode { 314 | type: "ClassProperty"; 315 | key: any; 316 | value: any; 317 | typeAnnotation: any; 318 | decorators: any; 319 | } 320 | 321 | declare class BabelNodeDeclareClass extends BabelNode { 322 | type: "DeclareClass"; 323 | id: any; 324 | typeParameters: any; 325 | body: any; 326 | } 327 | 328 | declare class BabelNodeDeclareFunction extends BabelNode { 329 | type: "DeclareFunction"; 330 | id: any; 331 | } 332 | 333 | declare class BabelNodeDeclareInterface extends BabelNode { 334 | type: "DeclareInterface"; 335 | id: any; 336 | typeParameters: any; 337 | body: any; 338 | } 339 | 340 | declare class BabelNodeDeclareModule extends BabelNode { 341 | type: "DeclareModule"; 342 | id: any; 343 | body: any; 344 | } 345 | 346 | declare class BabelNodeDeclareTypeAlias extends BabelNode { 347 | type: "DeclareTypeAlias"; 348 | id: any; 349 | typeParameters: any; 350 | right: any; 351 | } 352 | 353 | declare class BabelNodeDeclareVariable extends BabelNode { 354 | type: "DeclareVariable"; 355 | id: any; 356 | } 357 | 358 | declare class BabelNodeExistentialTypeParam extends BabelNode { 359 | type: "ExistentialTypeParam"; 360 | } 361 | 362 | declare class BabelNodeFunctionTypeAnnotation extends BabelNode { 363 | type: "FunctionTypeAnnotation"; 364 | typeParameters: any; 365 | params: any; 366 | rest: any; 367 | returnType: any; 368 | } 369 | 370 | declare class BabelNodeFunctionTypeParam extends BabelNode { 371 | type: "FunctionTypeParam"; 372 | name: any; 373 | typeAnnotation: any; 374 | } 375 | 376 | declare class BabelNodeInterfaceExtends extends BabelNode { 377 | type: "InterfaceExtends"; 378 | id: any; 379 | typeParameters: any; 380 | } 381 | 382 | declare class BabelNodeInterfaceDeclaration extends BabelNode { 383 | type: "InterfaceDeclaration"; 384 | id: any; 385 | typeParameters: any; 386 | body: any; 387 | } 388 | 389 | declare class BabelNodeIntersectionTypeAnnotation extends BabelNode { 390 | type: "IntersectionTypeAnnotation"; 391 | types: any; 392 | } 393 | 394 | declare class BabelNodeMixedTypeAnnotation extends BabelNode { 395 | type: "MixedTypeAnnotation"; 396 | } 397 | 398 | declare class BabelNodeNullableTypeAnnotation extends BabelNode { 399 | type: "NullableTypeAnnotation"; 400 | typeAnnotation: any; 401 | } 402 | 403 | declare class BabelNodeNumericLiteralTypeAnnotation extends BabelNode { 404 | type: "NumericLiteralTypeAnnotation"; 405 | } 406 | 407 | declare class BabelNodeNumberTypeAnnotation extends BabelNode { 408 | type: "NumberTypeAnnotation"; 409 | } 410 | 411 | declare class BabelNodeStringLiteralTypeAnnotation extends BabelNode { 412 | type: "StringLiteralTypeAnnotation"; 413 | } 414 | 415 | declare class BabelNodeStringTypeAnnotation extends BabelNode { 416 | type: "StringTypeAnnotation"; 417 | } 418 | 419 | declare class BabelNodeThisTypeAnnotation extends BabelNode { 420 | type: "ThisTypeAnnotation"; 421 | } 422 | 423 | declare class BabelNodeTupleTypeAnnotation extends BabelNode { 424 | type: "TupleTypeAnnotation"; 425 | types: any; 426 | } 427 | 428 | declare class BabelNodeTypeofTypeAnnotation extends BabelNode { 429 | type: "TypeofTypeAnnotation"; 430 | argument: any; 431 | } 432 | 433 | declare class BabelNodeTypeAlias extends BabelNode { 434 | type: "TypeAlias"; 435 | id: any; 436 | typeParameters: any; 437 | right: any; 438 | } 439 | 440 | declare class BabelNodeTypeAnnotation extends BabelNode { 441 | type: "TypeAnnotation"; 442 | typeAnnotation: any; 443 | } 444 | 445 | declare class BabelNodeTypeCastExpression extends BabelNode { 446 | type: "TypeCastExpression"; 447 | expression: any; 448 | typeAnnotation: any; 449 | } 450 | 451 | declare class BabelNodeTypeParameterDeclaration extends BabelNode { 452 | type: "TypeParameterDeclaration"; 453 | params: any; 454 | } 455 | 456 | declare class BabelNodeTypeParameterInstantiation extends BabelNode { 457 | type: "TypeParameterInstantiation"; 458 | params: any; 459 | } 460 | 461 | declare class BabelNodeObjectTypeAnnotation extends BabelNode { 462 | type: "ObjectTypeAnnotation"; 463 | properties: any; 464 | indexers: any; 465 | callProperties: any; 466 | } 467 | 468 | declare class BabelNodeObjectTypeCallProperty extends BabelNode { 469 | type: "ObjectTypeCallProperty"; 470 | value: any; 471 | } 472 | 473 | declare class BabelNodeObjectTypeIndexer extends BabelNode { 474 | type: "ObjectTypeIndexer"; 475 | id: any; 476 | key: any; 477 | value: any; 478 | } 479 | 480 | declare class BabelNodeObjectTypeProperty extends BabelNode { 481 | type: "ObjectTypeProperty"; 482 | key: any; 483 | value: any; 484 | } 485 | 486 | declare class BabelNodeQualifiedTypeIdentifier extends BabelNode { 487 | type: "QualifiedTypeIdentifier"; 488 | id: any; 489 | qualification: any; 490 | } 491 | 492 | declare class BabelNodeUnionTypeAnnotation extends BabelNode { 493 | type: "UnionTypeAnnotation"; 494 | types: any; 495 | } 496 | 497 | declare class BabelNodeVoidTypeAnnotation extends BabelNode { 498 | type: "VoidTypeAnnotation"; 499 | } 500 | 501 | declare class BabelNodeJSXAttribute extends BabelNode { 502 | type: "JSXAttribute"; 503 | name: BabelNodeJSXIdentifier | BabelNodeJSXNamespacedName; 504 | value?: ?BabelNodeJSXElement | BabelNodeStringLiteral | BabelNodeJSXExpressionContainer; 505 | } 506 | 507 | declare class BabelNodeJSXClosingElement extends BabelNode { 508 | type: "JSXClosingElement"; 509 | name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression; 510 | } 511 | 512 | declare class BabelNodeJSXElement extends BabelNode { 513 | type: "JSXElement"; 514 | openingElement: BabelNodeJSXOpeningElement; 515 | closingElement?: ?BabelNodeJSXClosingElement; 516 | children: any; 517 | selfClosing: any; 518 | } 519 | 520 | declare class BabelNodeJSXEmptyExpression extends BabelNode { 521 | type: "JSXEmptyExpression"; 522 | } 523 | 524 | declare class BabelNodeJSXExpressionContainer extends BabelNode { 525 | type: "JSXExpressionContainer"; 526 | expression: BabelNodeExpression; 527 | } 528 | 529 | declare class BabelNodeJSXIdentifier extends BabelNode { 530 | type: "JSXIdentifier"; 531 | name: string; 532 | } 533 | 534 | declare class BabelNodeJSXMemberExpression extends BabelNode { 535 | type: "JSXMemberExpression"; 536 | object: BabelNodeJSXMemberExpression | BabelNodeJSXIdentifier; 537 | property: BabelNodeJSXIdentifier; 538 | } 539 | 540 | declare class BabelNodeJSXNamespacedName extends BabelNode { 541 | type: "JSXNamespacedName"; 542 | namespace: BabelNodeJSXIdentifier; 543 | name: BabelNodeJSXIdentifier; 544 | } 545 | 546 | declare class BabelNodeJSXOpeningElement extends BabelNode { 547 | type: "JSXOpeningElement"; 548 | name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression; 549 | selfClosing?: boolean; 550 | attributes: any; 551 | } 552 | 553 | declare class BabelNodeJSXSpreadAttribute extends BabelNode { 554 | type: "JSXSpreadAttribute"; 555 | argument: BabelNodeExpression; 556 | } 557 | 558 | declare class BabelNodeJSXText extends BabelNode { 559 | type: "JSXText"; 560 | value: string; 561 | } 562 | 563 | declare class BabelNodeNoop extends BabelNode { 564 | type: "Noop"; 565 | } 566 | 567 | declare class BabelNodeParenthesizedExpression extends BabelNode { 568 | type: "ParenthesizedExpression"; 569 | expression: BabelNodeExpression; 570 | } 571 | 572 | declare class BabelNodeAwaitExpression extends BabelNode { 573 | type: "AwaitExpression"; 574 | argument: BabelNodeExpression; 575 | } 576 | 577 | declare class BabelNodeBindExpression extends BabelNode { 578 | type: "BindExpression"; 579 | object: any; 580 | callee: any; 581 | } 582 | 583 | declare class BabelNodeDecorator extends BabelNode { 584 | type: "Decorator"; 585 | expression: BabelNodeExpression; 586 | } 587 | 588 | declare class BabelNodeDoExpression extends BabelNode { 589 | type: "DoExpression"; 590 | body: BabelNodeBlockStatement; 591 | } 592 | 593 | declare class BabelNodeExportDefaultSpecifier extends BabelNode { 594 | type: "ExportDefaultSpecifier"; 595 | exported: BabelNodeIdentifier; 596 | } 597 | 598 | declare class BabelNodeExportNamespaceSpecifier extends BabelNode { 599 | type: "ExportNamespaceSpecifier"; 600 | exported: BabelNodeIdentifier; 601 | } 602 | 603 | declare class BabelNodeRestProperty extends BabelNode { 604 | type: "RestProperty"; 605 | argument: BabelNodeLVal; 606 | } 607 | 608 | declare class BabelNodeSpreadProperty extends BabelNode { 609 | type: "SpreadProperty"; 610 | argument: BabelNodeExpression; 611 | } 612 | -------------------------------------------------------------------------------- /hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | npm test 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fjs", 3 | "version": "1.0.0", 4 | "description": "format js", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest", 8 | "postinstall": "ln -s -f ../../hooks/pre-commit .git/hooks/pre-commit" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/kyldvs/fjs.git" 13 | }, 14 | "author": "Kyle Davis", 15 | "license": "ISC", 16 | "dependencies": { 17 | "babel-plugin-syntax-async-functions": "^6.8.0", 18 | "babel-plugin-syntax-flow": "^6.8.0", 19 | "babel-plugin-syntax-jsx": "^6.8.0", 20 | "babel-plugin-syntax-object-rest-spread": "^6.8.0", 21 | "babel-plugin-syntax-trailing-function-commas": "^6.8.0" 22 | }, 23 | "devDependencies": { 24 | "babel-core": "^6.7.6", 25 | "babel-jest": "^13.0.0", 26 | "babel-plugin-syntax-flow": "^6.5.0", 27 | "babel-plugin-syntax-jsx": "^6.5.0", 28 | "babel-plugin-syntax-object-rest-spread": "^6.5.0", 29 | "babel-plugin-syntax-trailing-function-commas": "^6.5.0", 30 | "babel-plugin-transform-flow-strip-types": "^6.5.0", 31 | "babel-plugin-transform-object-rest-spread": "^6.6.5", 32 | "babel-plugin-transform-react-jsx": "^6.7.5", 33 | "babel-plugin-transform-regenerator": "^6.5.2", 34 | "babel-plugin-transform-runtime": "^6.5.2", 35 | "babel-preset-es2015": "^6.5.0", 36 | "babel-types": "^6.11.1", 37 | "jest": "^13.3.0-alpha" 38 | }, 39 | "jest": { 40 | "modulePathIgnorePatterns": [ 41 | "/node_modules/" 42 | ], 43 | "preprocessorIgnorePatterns": [ 44 | "/node_modules/" 45 | ], 46 | "rootDir": "", 47 | "testPathDirs": [ 48 | "/src" 49 | ], 50 | "unmockedModulePathPatterns": [ 51 | ".*" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Printers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | import {map, printList} from './utils'; 10 | 11 | /** 12 | * These are not first-class printers. They are helpers for common patterns. 13 | * For example there are many different ways to represent something that looks 14 | * like an assignment, and they are all printed the same. 15 | */ 16 | export default { 17 | Array: ({print, elements}) => [ 18 | Tokens.string('['), 19 | printList(elements, print), 20 | Tokens.string(']'), 21 | ], 22 | 23 | Assignment: ({print, left, right}) => [ 24 | print(left), 25 | Tokens.space(), 26 | Tokens.string('='), 27 | right && [ 28 | right.type === 'JSXElement' && [ 29 | Tokens.scopeOpen('jsx_after_assignment'), 30 | Tokens.scopeSpaceOrBreak(), 31 | print(right), 32 | Tokens.scopeClose(), 33 | ], 34 | right.type !== 'JSXElement' && [ 35 | Tokens.space(), 36 | print(right), 37 | ], 38 | ], 39 | ], 40 | 41 | Function: ({ 42 | async: async, 43 | body, 44 | generator, 45 | id, 46 | params, 47 | print, 48 | }) => [ 49 | async && [ 50 | Tokens.string('async'), 51 | Tokens.space(), 52 | ], 53 | Tokens.string('function'), 54 | Tokens.space(), 55 | generator && Tokens.string('*'), 56 | print(id), 57 | Tokens.string('('), 58 | params && printList(params, print), 59 | Tokens.string(')'), 60 | Tokens.space(), 61 | print(body), 62 | ], 63 | 64 | Object: ({print, properties}) => [ 65 | Tokens.string('{'), 66 | properties.length && [ 67 | Tokens.scopeOpen('object'), 68 | map(properties, (property, i, arr) => [ 69 | Tokens.scopeSpaceOrBreak(), 70 | print(property), 71 | arr.length - 1 !== i ? Tokens.comma() : Tokens.scopeEmptyOrComma(), 72 | ]), 73 | Tokens.scopeSpaceOrBreak(), 74 | Tokens.scopeClose(), 75 | ], 76 | Tokens.string('}'), 77 | ], 78 | 79 | String: ({value, quotes}) => [ 80 | quotes === 'double' && Tokens.string(JSON.stringify(value)), 81 | quotes === 'single' && Tokens.string(escapeStringLiteral(value)), 82 | ], 83 | }; 84 | 85 | function escapeStringLiteral(value) { 86 | return swapQuotes(JSON.stringify(swapQuotes(value))); 87 | } 88 | 89 | function swapQuotes(str) { 90 | return str.replace(/['"]/g, m => { 91 | return m === '"' ? '\'' : '"'; 92 | }); 93 | } 94 | -------------------------------------------------------------------------------- /src/Tokens.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const Tokens = { 8 | // Tokens related to scopes. 9 | scopeOpen: (kind) => ({ 10 | type: 'scopeOpen', 11 | scope: true, 12 | unbroken: Tokens.empty(), 13 | broken: Tokens.indent(), 14 | kind, 15 | }), 16 | 17 | scopeOpenNoIndent: (kind) => ({ 18 | type: 'scopeOpen', 19 | scope: true, 20 | unbroken: Tokens.empty(), 21 | broken: Tokens.empty(), 22 | kind, 23 | }), 24 | 25 | scopeClose: () => ({ 26 | type: 'scopeClose', 27 | scope: true, 28 | unbroken: Tokens.empty(), 29 | broken: Tokens.dedent(), 30 | }), 31 | 32 | scopeCloseNoDedent: () => ({ 33 | type: 'scopeClose', 34 | scope: true, 35 | unbroken: Tokens.empty(), 36 | broken: Tokens.empty(), 37 | }), 38 | 39 | scope: (unbroken, broken) => ({ 40 | type: 'scope', 41 | scope: true, 42 | unbroken, 43 | broken, 44 | }), 45 | 46 | scopeEmptyOrBreak: () => Tokens.scope(Tokens.empty(), Tokens.break()), 47 | scopeEmptyOrComma: () => Tokens.scope(Tokens.empty(), Tokens.comma()), 48 | scopeSpaceOrBreak: () => Tokens.scope(Tokens.space(), Tokens.break()), 49 | scopeEmptyOrOpenParen: () => Tokens.scope(Tokens.empty(), Tokens.string('(')), 50 | scopeEmptyOrCloseParen: () => Tokens.scope( 51 | Tokens.empty(), 52 | Tokens.string(')'), 53 | ), 54 | scopeEmptyOrIndent: () => Tokens.scope(Tokens.empty(), Tokens.indent()), 55 | scopeEmptyOrDedent: () => Tokens.scope(Tokens.empty(), Tokens.dedent()), 56 | 57 | // Whitespace tokens. 58 | empty: () => ({ 59 | type: 'empty', 60 | }), 61 | 62 | space: () => ({ 63 | type: 'space', 64 | }), 65 | 66 | break: () => ({ 67 | type: 'break', 68 | }), 69 | 70 | canBreak: () => ({ 71 | type: 'canBreak', 72 | }), 73 | 74 | indent: () => ({ 75 | type: 'indent', 76 | }), 77 | 78 | dedent: () => ({ 79 | type: 'dedent', 80 | }), 81 | 82 | // Punctuation. 83 | colon: () => ({ 84 | type: 'colon', 85 | }), 86 | 87 | comma: () => ({ 88 | type: 'comma', 89 | }), 90 | 91 | semiColon: () => ({ 92 | type: 'semiColon', 93 | }), 94 | 95 | period: () => ({ 96 | type: 'period', 97 | }), 98 | 99 | questionMark: () => ({ 100 | type: 'questionMark', 101 | }), 102 | 103 | // Final string token. These will be printed exactly in the result. 104 | string: (value) => ({ 105 | type: 'string', 106 | value, 107 | }), 108 | }; 109 | 110 | export default Tokens; 111 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-indentation/hard-tab.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | bar(); 3 | if (foo) { 4 | bar(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-indentation/soft-tab-2.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | bar(); 3 | if (foo) { 4 | bar(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-indentation/soft-tab-4.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | bar(); 3 | if (foo) { 4 | bar(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-string/double.js: -------------------------------------------------------------------------------- 1 | foo("foo"); 2 | foo("foo\nlol"); 3 | foo("foo\n\"lol"); 4 | foo("foo\n\"'lol"); 5 | foo("😂"); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-string/jsx.js: -------------------------------------------------------------------------------- 1 | var single = 'quotes'; 2 | var outnumber = 'double'; 3 | var moreSingleQuotesThanDouble = '!'; 4 | 5 | React.createClass({ 6 | render() { 7 | return ; 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/auto-string/single.js: -------------------------------------------------------------------------------- 1 | foo('foo'); 2 | foo('foo\nlol'); 3 | foo('foo\n"lol'); 4 | foo('foo\n"\'lol'); 5 | foo('😂'); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/2-space-multi-comment-with-space.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | 3 | 4 | /* 5 | * this is comment 6 | */ 7 | 8 | 9 | var i = 20; 10 | } 11 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/2-space-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * this is comment 4 | */ 5 | var i = 20; 6 | } 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/block-line-comment-with-concise-format.js: -------------------------------------------------------------------------------- 1 | { 2 | print("hello"); 3 | // comment 4 | } 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/block-line-comment-with-retainlines-option.js: -------------------------------------------------------------------------------- 1 | { 2 | print("hello"); 3 | // comment 4 | } 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/block-line-comment.js: -------------------------------------------------------------------------------- 1 | // Leading to block 2 | { 3 | print("hello"); 4 | } 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/comment-only-with-space.js: -------------------------------------------------------------------------------- 1 | 2 | // from #23 3 | 4 | /**/ 5 | 6 | /* 7 | */ 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/comment-only.js: -------------------------------------------------------------------------------- 1 | // from #23 2 | /**/ 3 | /* 4 | */ 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/comment-statement-with-retainlines-option.js: -------------------------------------------------------------------------------- 1 | // comment 2 | print("hello"); 3 | 4 | // comment2 5 | print("hello2"); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/computed-property-comments-2.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ["a"]:"1", 6 | [/* 7 | * Inside bracket init 8 | */ 9 | "b"]:"2" 10 | }, ok = 42; 11 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/computed-property-comments.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ["a"]:"1", 6 | 7 | [/* 8 | * Inside bracket init 9 | */ 10 | "b"]:"2", 11 | 12 | ["c" 13 | /* 14 | * After bracket key 15 | */]:"3", 16 | 17 | // Before bracket, line comment 18 | [ 19 | "d"]:"4", 20 | 21 | [ 22 | // Inside bracket, line comment 23 | "e"]:"5", 24 | 25 | ["f" 26 | // After bracket, line comment 27 | ]:"6" 28 | }; 29 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/do-while-line-comment.js: -------------------------------------------------------------------------------- 1 | do { 2 | } // LINE 3 | while (true); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/empty-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading to EmptyStatement 3 | ; // Trailing to EmptyStatement 4 | } 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/empty.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/function-block-line-comment.js: -------------------------------------------------------------------------------- 1 | !function(){}// 2 | ,42; 3 | !{get 42(){}// 4 | ,foo:42}; 5 | (function(){}// 6 | ) 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/if-block-line-comment.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to if-block 3 | { 4 | print("hello"); 5 | } // Trailing to if-block 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/if-empty-line-comment.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to EmptyStatement 3 | ; // Trailing to EmptyStatement 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/if-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading if statement 3 | if (cond) {print("hello") } 4 | // Trailing if-block statement 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/object_comments.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Test 2 4 | */ 5 | a:"1", 6 | /* 7 | * Test 1 8 | */ 9 | b:"2", 10 | // Test 3 11 | c:"3" 12 | }; 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/return-no-argument.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | return; // comment 3 | }()); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/simple-a-lot-of-line-comment.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Yusuke Suzuki 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above copyright 9 | // notice, this list of conditions and the following disclaimer in the 10 | // documentation and/or other materials provided with the distribution. 11 | // 12 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 16 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | 24 | function test() { 25 | } 26 | 27 | 28 | 29 | // Copyright (C) 2012 Yusuke Suzuki 30 | // 31 | // Redistribution and use in source and binary forms, with or without 32 | // modification, are permitted provided that the following conditions are met: 33 | // 34 | // * Redistributions of source code must retain the above copyright 35 | // notice, this list of conditions and the following disclaimer. 36 | // * Redistributions in binary form must reproduce the above copyright 37 | // notice, this list of conditions and the following disclaimer in the 38 | // documentation and/or other materials provided with the distribution. 39 | // 40 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 41 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 44 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 45 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 48 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 49 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/simple-a-lot-of-multi-comment.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | function test() { 26 | 27 | } 28 | 29 | /* 30 | Copyright (C) 2012 Yusuke Suzuki 31 | 32 | Redistribution and use in source and binary forms, with or without 33 | modification, are permitted provided that the following conditions are met: 34 | 35 | * Redistributions of source code must retain the above copyright 36 | notice, this list of conditions and the following disclaimer. 37 | * Redistributions in binary form must reproduce the above copyright 38 | notice, this list of conditions and the following disclaimer in the 39 | documentation and/or other materials provided with the distribution. 40 | 41 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 42 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 45 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 46 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 48 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 50 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 | */ 52 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/simple-line-comment.js: -------------------------------------------------------------------------------- 1 | // Leading 2 | var i = 20; 3 | // Trailing 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/simple-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * Leading comment 4 | */ 5 | 6 | /* 7 | * 8 | * Leading comment 2 9 | * 10 | */ 11 | 12 | var i = 20; 13 | /* 14 | * Trailing comment 15 | */ 16 | 17 | /* 18 | * 19 | * Trailing comment 2 20 | * 21 | */ 22 | } 23 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/simple-statement-comment.js: -------------------------------------------------------------------------------- 1 | ; // Trailing 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/try-block-line-comment.js: -------------------------------------------------------------------------------- 1 | try{}// 2 | finally{} 3 | 4 | try{} 5 | catch(e){}// 6 | finally{} 7 | 8 | { 9 | try{} 10 | catch(e){}// 11 | finally{} 12 | } 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/variable-declarator-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | // Leading to VariableDeclarator 4 | // Leading to VariableDeclarator 5 | i = 20, 6 | // Leading to VariableDeclarator 7 | // Leading to VariableDeclarator 8 | j = 20; 9 | } 10 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/variable-declarator-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | /* 4 | * Leading to VariableDeclarator 5 | * Leading to VariableDeclarator 6 | */ 7 | i = 20, 8 | /* 9 | * Leading to VariableDeclarator 10 | * Leading to VariableDeclarator 11 | */ 12 | j = 20; 13 | } 14 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/comments/variable-declarator-trailing-comment.js: -------------------------------------------------------------------------------- 1 | { 2 | var t = 20; /* 3 | * This is trailing comment 4 | */ 5 | } 6 | 7 | { 8 | var tt = 20; /* 9 | * This is trailing comment 10 | */ 11 | } 12 | {{ 13 | var t = 20; /* 14 | * This is trailing comment 15 | */ 16 | }} 17 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/compact/assignment.js: -------------------------------------------------------------------------------- 1 | x = 1; 2 | var { y = 1 } = obj; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/compact/binary-expressions.js: -------------------------------------------------------------------------------- 1 | 1 * 1; 2 | 1 && 1; 3 | 1 + +1; 4 | x + ++y; 5 | (a+(+b)*2); 6 | a + +b * 2 * 2 * 2; 7 | a - -b; 8 | 1 + -b; 9 | 1 - --b; 10 | a - -b * 2; 11 | 1 - (--t) * t; 12 | 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/compact/single-line-comment.js: -------------------------------------------------------------------------------- 1 | // foo 2 | bar(); 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/compact/while.js: -------------------------------------------------------------------------------- 1 | while(true) x(); 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/bitwise-precedence.js: -------------------------------------------------------------------------------- 1 | x | y ^ z; 2 | x | (y ^ z); 3 | (x | y) ^ z; 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/floating-point.js: -------------------------------------------------------------------------------- 1 | 1.1.valueOf(); 2 | (1e+300).valueOf(); 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/for-in-no-in.js: -------------------------------------------------------------------------------- 1 | //for (var i = (1 in []) in []); 2 | //for (var i = 1 in [] in []); 3 | //for (var i = (10 * 10 in []) in []); 4 | //for (var i = (10 + 10 in []) in []); 5 | //for (var i = 10 + (10 in []) in []); 6 | //for (var i = 10 + 10 in [] in []); 7 | for (var i = (1 in []);;); 8 | for ((1 in []);;); 9 | for (1 * (1 in []);;); 10 | for (1 * (1 + 1 in []);;); 11 | for (1 * ((1 + 1) in []);;); 12 | for (1 * (1 + (1 in []));;); 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/for-loop-in.js: -------------------------------------------------------------------------------- 1 | for ((a in b) ? a : b; i;); 2 | for (function(){for(;;);} && (a in b);;); 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/member-expression-numeric-literals.js: -------------------------------------------------------------------------------- 1 | 1..toString; 2 | 2..toString(); 3 | 0x1F7.toString(); 4 | 0b111110111.toString(); 5 | 0o767.toString(); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/new-precedence.js: -------------------------------------------------------------------------------- 1 | new (a().b)(); 2 | new a().b(); 3 | new (a()).b(); 4 | new (a())(); 5 | new new a(a)(); 6 | new (new a())(a); 7 | (new a()).test; 8 | (new a().test); 9 | (new (a().test)()); 10 | new (a().b.c)(); 11 | new a().b.c(); 12 | new (a.b().c.d)(); 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/one-property-with-line-terminator.js: -------------------------------------------------------------------------------- 1 | dejavu.Class.declare({ 2 | method2: function () {} 3 | }); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/return-with-retainlines-and-compact-option.js: -------------------------------------------------------------------------------- 1 | function foo(l) { 2 | return ( 3 | // hi 4 | l 5 | ); 6 | } 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/return-with-retainlines-option.js: -------------------------------------------------------------------------------- 1 | function foo(l) { 2 | return ( 3 | l 4 | ); 5 | } 6 | 7 | function foo() { 8 | return ( 9 | 1 && 2 10 | ) || 3; 11 | } 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/unary-op.js: -------------------------------------------------------------------------------- 1 | delete delete i; 2 | + +i; 3 | !!i; 4 | + ++i; 5 | - --i; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/edgecase/variable-declaration.js: -------------------------------------------------------------------------------- 1 | var fact5 = function fact(n){ 2 | if (n <= 1) return 1 3 | return n * fact(n - 1) 4 | }(5) 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/array-types.js: -------------------------------------------------------------------------------- 1 | var a: number[]; 2 | var a: ?number[]; 3 | var a: (?number)[]; 4 | var a: () => number[]; 5 | var a: (() => number)[]; 6 | var a: typeof A[]; 7 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/boolean-literal-types.js: -------------------------------------------------------------------------------- 1 | var foo: true; 2 | var bar: false; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/call-properties.js: -------------------------------------------------------------------------------- 1 | var a: { (): number }; 2 | var a: { (): number; }; 3 | var a: { (): number; y: string; (x: string): string }; 4 | var a: { (x: T): number; }; 5 | interface A { (): number; }; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/declare-module.js: -------------------------------------------------------------------------------- 1 | declare module A {} 2 | declare module "./a/b.js" {} 3 | declare module A { declare var x: number; } 4 | declare module A { declare function foo(): number; } 5 | declare module A { declare class B { foo(): number; } } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/declare-statements.js: -------------------------------------------------------------------------------- 1 | declare var foo 2 | declare var foo; 3 | declare function foo(): void 4 | declare function foo(): void; 5 | declare function foo(): void; 6 | declare function foo(x: number, y: string): void; 7 | declare class A {} 8 | declare class A extends B { x: number } 9 | declare class A { static foo(): number; static x : string } 10 | declare class A { static [ indexer: number]: string } 11 | declare class A { static () : number } 12 | declare class A mixins B, C {} 13 | declare type A = string 14 | declare type T = { [k:string]: U } 15 | declare interface I { foo: string } 16 | declare interface I { foo: T } 17 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/def-site-variance.js: -------------------------------------------------------------------------------- 1 | class C<+T, -U> {} 2 | function f<+T, -U>() {} 3 | type T<+T, -U> = {}; 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/interfaces-module-and-script.js: -------------------------------------------------------------------------------- 1 | interface A {}; 2 | interface A extends B {}; 3 | interface A extends B, C {}; 4 | interface A { foo: () => number; }; 5 | interface Dictionary { [index: string]: string; length: number; }; 6 | class Foo implements Bar {} 7 | class Foo extends Bar implements Bat, Man {} 8 | class Foo extends class Bar implements Bat {} {} 9 | class Foo extends class Bar implements Bat {} implements Man {} 10 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/null-literal-types.js: -------------------------------------------------------------------------------- 1 | var foo: null; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/number-literal-types.js: -------------------------------------------------------------------------------- 1 | var a: 123; 2 | var a: 123.0; 3 | var a: 0x7B; 4 | var a: 0b1111011; 5 | var a: 0o173; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/qualified-generic-type.js: -------------------------------------------------------------------------------- 1 | var a: A.B; 2 | var a: A.B.C; 3 | var a: A.B; 4 | var a: typeof A.B; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/string-literal-types.js: -------------------------------------------------------------------------------- 1 | function createElement(tagName: "div"): HTMLDivElement {} 2 | function createElement(tagName: 'div'): HTMLDivElement {} 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/this-types.js: -------------------------------------------------------------------------------- 1 | class Foo { 2 | bar(): this { 3 | return this; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/tuples.js: -------------------------------------------------------------------------------- 1 | var a: [] = []; 2 | var a: [Foo] = [foo]; 3 | var a: [number,] = [123,]; 4 | var a: [number, string] = [123, "duck"]; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/type-alias.js: -------------------------------------------------------------------------------- 1 | type FBID = number; 2 | type Foo = Bar; 3 | type Maybe = _Maybe; 4 | export type Foo = number; 5 | 6 | type union = 7 | | {type: "A"} 8 | | {type: "B"} 9 | ; 10 | 11 | type overloads = 12 | & ((x: string) => number) 13 | & ((x: number) => string) 14 | ; 15 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/type-annotations.js: -------------------------------------------------------------------------------- 1 | function foo(numVal: any) {} 2 | function foo(numVal: number) {} 3 | function foo(numVal: number, strVal: string) {} 4 | function foo(numVal: number, untypedVal) {} 5 | function foo(untypedVal, numVal: number) {} 6 | function foo(nullableNum: ?number) {} 7 | function foo(callback: () => void) {} 8 | function foo(callback: () => number) {} 9 | function foo(callback: (_: bool) => number) {} 10 | function foo(callback: (_1: bool, _2: string) => number) {} 11 | function foo(callback: (_1: bool, ...foo: Array) => number) {} 12 | function foo(): number{} 13 | function foo():() => void {} 14 | function foo():(_:bool) => number{} 15 | function foo():(_?:bool) => number{} 16 | function foo(): {} {} 17 | function foo() {} 18 | function foo() {} 19 | function foo() {} 20 | a = function() {}; 21 | a = { set fooProp(value: number) {} }; 22 | a = { set fooProp(value: number): void {} }; 23 | a = { get fooProp():number{} }; 24 | a = { id(x: T): T {} }; 25 | a = { *id(x: T): T {} }; 26 | a = { async id(x: T): T {} }; 27 | a = { 123(x: T): T {} }; 28 | class Foo { 29 | set fooProp(value: number) {} 30 | } 31 | class Foo { 32 | set fooProp(value: number): void {} 33 | } 34 | class Foo { 35 | get fooProp(): number {} 36 | } 37 | var numVal: number; 38 | var numVal: number = otherNumVal; 39 | var a: { numVal: number }; 40 | var a: { numVal: number; }; 41 | var a: { numVal: number; [indexer: string]: number }; 42 | var a: ?{ numVal: number }; 43 | var a: { numVal: number; strVal: string } 44 | var a: { subObj: {strVal: string} } 45 | var a: { subObj: ?{strVal: string} } 46 | var a: { param1: number; param2: string } 47 | var a: { param1: number; param2?: string } 48 | var a: { [a: number]: string; [b: number]: string; }; 49 | var a: { add(x: number, ...y: Array): void }; 50 | var a: { id(x: T): T; }; 51 | var a:Array = [1, 2, 3] 52 | a = class Foo {} 53 | a = class Foo extends Bar {} 54 | class Foo {} 55 | class Foo extends Bar {} 56 | class Foo extends mixin(Bar) {} 57 | class Foo { 58 | bar():number { return 42; } 59 | } 60 | class Foo { 61 | "bar"() {} 62 | } 63 | function foo(requiredParam, optParam?) {} 64 | class Foo { 65 | prop1: string; 66 | prop2: number; 67 | } 68 | class Foo { 69 | static prop1: string; 70 | prop2: number; 71 | } 72 | var x: number | string = 4; 73 | class Array { concat(items:number | string) {}; } 74 | var x: () => number | () => string = fn; 75 | var x: typeof Y = Y; 76 | var x: typeof Y | number = Y; 77 | var {x}: {x: string; } = { x: "hello" }; 78 | var {x}: {x: string } = { x: "hello" }; 79 | var [x]: Array = [ "hello" ]; 80 | function foo({x}: { x: string; }) {} 81 | function foo([x]: Array) {} 82 | function foo(...rest: Array) {} 83 | (function (...rest: Array) {}); 84 | ((...rest: Array) => rest); 85 | var a: Map > 86 | var a: Map> 87 | var a: number[] 88 | var a: ?string[] 89 | var a: Promise[] 90 | var a:(...rest:Array) => number 91 | var identity: (x: T) => T 92 | var identity: (x: T, ...y:T[]) => T 93 | import type foo from "bar"; 94 | import type { foo, bar } from "baz"; 95 | import type { foo as bar } from "baz"; 96 | import type from "foo"; 97 | import type, { foo } from "bar"; 98 | import type * as namespace from "bar"; 99 | export type { foo }; 100 | export type { foo } from "bar"; 101 | export interface foo { p: number }; 102 | export interface foo { p: T }; 103 | var a: ?Array; 104 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/type-parameters.js: -------------------------------------------------------------------------------- 1 | type A = T; 2 | type A = T; 3 | type A = T; 4 | type A = T; 5 | type A = T; 6 | class A {}; 7 | class A {}; 8 | class A {}; 9 | class A {}; 10 | (class A {}); 11 | (class A {}); 12 | (class A {}); 13 | (class A {}); 14 | declare class A {}; 15 | declare class A {}; 16 | declare class A {}; 17 | declare class A {}; 18 | interface A {}; 19 | interface A {}; 20 | interface A {}; 21 | interface A {}; 22 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/flow/typecasts.js: -------------------------------------------------------------------------------- 1 | (xxx: number); 2 | ({ xxx: 0, yyy: "hey" }: { xxx: number; yyy: string }); 3 | (xxx => xxx + 1: (xxx: number) => number); 4 | ((xxx: number), (yyy: string)); 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/arrow-function.js: -------------------------------------------------------------------------------- 1 | e => { 2 | print("hello world"); 3 | }; 4 | (e1, e2, e3) => { 5 | print("hello world"); 6 | }; 7 | e => e; 8 | (e1, e2, e3) => e; 9 | (e) => { 10 | }; 11 | e => 20 + 20 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/class-declaration.js: -------------------------------------------------------------------------------- 1 | class Test { 2 | } 3 | class Derived extends Super { 4 | } 5 | class StaticMethods { 6 | static n1() { 7 | } 8 | 9 | static get get1() { 10 | } 11 | 12 | static set set1(value) { 13 | } 14 | 15 | static *gen1() { 16 | } 17 | } 18 | class Methods { 19 | n2() { 20 | } 21 | 22 | get get2() { 23 | } 24 | 25 | set set2(value) { 26 | } 27 | 28 | *gen1() { 29 | } 30 | } 31 | class ComputedStaticMethods { 32 | static [n1]() { 33 | } 34 | 35 | static get [get1]() { 36 | } 37 | 38 | static set [set1](value) { 39 | } 40 | 41 | static *[gen1]() { 42 | } 43 | } 44 | class ComputedMethods { 45 | [n2]() { 46 | } 47 | 48 | get [get2]() { 49 | } 50 | 51 | set [set2](value) { 52 | } 53 | 54 | *[gen1]() { 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/class-expression.js: -------------------------------------------------------------------------------- 1 | (class Test { }); 2 | (class Derived extends Super { }); 3 | (class StaticMethods { 4 | static n1() { 5 | } 6 | 7 | static get get1() { 8 | } 9 | 10 | static set set1(value) { 11 | } 12 | 13 | static *gen1() { 14 | } 15 | }); 16 | (class Methods { 17 | n2() { 18 | } 19 | 20 | get get2() { 21 | } 22 | 23 | set set2(value) { 24 | } 25 | 26 | *gen1() { 27 | } 28 | }); 29 | (class ComputedStaticMethods { 30 | static [n1]() { 31 | } 32 | 33 | static get [get1]() { 34 | } 35 | 36 | static set [set1](value) { 37 | } 38 | 39 | static *[gen1]() { 40 | } 41 | }); 42 | (class ComputedMethods { 43 | [n2]() { 44 | } 45 | 46 | get [get2]() { 47 | } 48 | 49 | set [set2](value) { 50 | } 51 | 52 | *[gen1]() { 53 | } 54 | }); 55 | (class { }); 56 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/computed-property.js: -------------------------------------------------------------------------------- 1 | var object1 = { 2 | get [Symbol.create]() { }, 3 | set [set()](value) { } 4 | }; 5 | var object2 = { 6 | *[generator()]() { } 7 | }; 8 | var object3 = { 9 | *[generator()]() { } 10 | }; 11 | var object4 = { 12 | [Symbol.xxx]: "hello", 13 | [ok()]: 42 14 | }; 15 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/default-parameter.js: -------------------------------------------------------------------------------- 1 | function a(p=20) { 2 | } 3 | 4 | function b(p, q=30) { 5 | } 6 | 7 | function c(p, q=30, ...r) { 8 | } 9 | 10 | (p = 20) => { }; 11 | (p = 20, ...q) => { }; 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/destructuring-assignment.js: -------------------------------------------------------------------------------- 1 | function t1({responseText: responseText}) { 2 | } 3 | function t2({responseText}) { 4 | } 5 | function t3([a, b]) { 6 | } 7 | var [i, j, k] = array; 8 | var { 9 | i, 10 | j, 11 | k 12 | } = obj; 13 | let {i, j, k} = obj; 14 | const {i, j, k} = obj; 15 | var { value } = obj; 16 | var { 17 | value 18 | } = obj; 19 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/export-default-declaration.js: -------------------------------------------------------------------------------- 1 | export default function a () { } 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/exports.js: -------------------------------------------------------------------------------- 1 | export * from "OK" 2 | export { name } from "OK" 3 | export { a as b, c as d } from "hello" 4 | export { a as b, c as d } 5 | export { } 6 | export default i = 20 7 | export function test() { } 8 | export class test2 { } 9 | export var i = 20 10 | export let i = 42 11 | 12 | export default (function(){})(); 13 | export default (class {})(); 14 | export default {}; 15 | 16 | export default function test3(){} 17 | export default class test4 {} 18 | 19 | export default function(){} 20 | export default class {} 21 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/for-of-statement.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | for (var i of array) { 3 | } 4 | 5 | for (let i of array) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/import-with-default.js: -------------------------------------------------------------------------------- 1 | import foo from "foo"; 2 | import * as foo from "foo"; 3 | import ok, { 4 | foo as bar, 5 | test as testing, 6 | logging 7 | } from "foo"; 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/imports.js: -------------------------------------------------------------------------------- 1 | import "foo"; 2 | import {foo} from "foo"; 3 | import {foo as bar} from "foo"; 4 | import { 5 | foo as bar, 6 | test as testing, 7 | logging 8 | } from "foo"; 9 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/spread-element.js: -------------------------------------------------------------------------------- 1 | var [a, b, ...rest] = array; 2 | const [a, b, ...rest] = array; 3 | function a([a, b, ...rest]) { 4 | } 5 | ([a, b, ...rest]) => { }; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/templates-escape.js: -------------------------------------------------------------------------------- 1 | var escaped = ` 2 | \u2028 3 | \u2029 4 | `; 5 | 6 | var escaped = ` 7 | \v 8 | \b 9 | \t 10 | \n 11 | \r 12 | `; 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/templates-indentation.js: -------------------------------------------------------------------------------- 1 | function multilineTemplate() { 2 | return `I'm done reconfoobling 3 | ${ 'the energy motron' } 4 | ${'...or whatever'}`; 5 | } 6 | 7 | { 8 | const foo = `spam 9 | and eggs!`; 10 | 11 | const bar = `${ 12 | 4 + 13 | 2 14 | }`; 15 | 16 | const hello = `Hello 17 | ${ 'world' }`; 18 | } 19 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/templates.js: -------------------------------------------------------------------------------- 1 | var hello = `hello`; 2 | 3 | var hello = ` 4 | line 5 | terminators`; 6 | 7 | var tagged = tagged`hello`; 8 | var tagged = member.call`hello`; 9 | var tagged = new call`hello`; 10 | var tagged = new (call`hello`()); 11 | var tageed = member[call`hello`]; 12 | 13 | var middles = ` 14 | Is the order a rabbit? 15 | `; 16 | 17 | var middles = ` 18 | Is the order ${ order }? 19 | `; 20 | 21 | var middles = ` 22 | Is the order ${ order }? 23 | `; 24 | 25 | var middles = ` 26 | 1. ${ cocoa } 27 | 2. ${ chino } 28 | 3. ${ rize } 29 | 4. ${ syaro } 30 | 5. ${ chiya } 31 | `; 32 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/harmony-edgecase/yield-precedence.js: -------------------------------------------------------------------------------- 1 | function *foo () { 2 | var a = yield wat(), b = 2; 3 | var c = yield a = b; 4 | yield a, yield b; 5 | yield a = b; 6 | return (yield 1) || (yield 2); 7 | } 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/arrow-functions.js: -------------------------------------------------------------------------------- 1 | var foo = (arg1, arg2) => { 2 | arg1; 3 | arg2; 4 | }; 5 | var foo2 = (arg1, arg2) => { 6 | arg1; 7 | }; 8 | var foo3 = arg1 => arg1; 9 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/block-statements.js: -------------------------------------------------------------------------------- 1 | if (true) { 2 | foo; 3 | bar2; 4 | } else { 5 | foo; 6 | bar2; 7 | } 8 | 9 | function fn () { 10 | foo; 11 | bar2; 12 | } 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/labeled-statement.js: -------------------------------------------------------------------------------- 1 | function x() { 2 | return -1; 3 | return --i; 4 | return !2; 5 | return void 0; 6 | } 7 | 8 | throw -1; 9 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/literals.js: -------------------------------------------------------------------------------- 1 | 5; 2 | 5.0; 3 | "foobar"; 4 | '\x20'; 5 | "\n\r"; 6 | "😂"; 7 | /foobar/g; 8 | null; 9 | true; 10 | false; 11 | 5.; 12 | 0b10; 13 | 0o70; 14 | 0X1F; 15 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/modules.js: -------------------------------------------------------------------------------- 1 | import * as foo from "foo"; 2 | import {foo as bar, foo2 as bar2} from "foo"; 3 | import {foo2} from "foo"; 4 | 5 | export * from "foo"; 6 | export {foo as bar} from "foo"; 7 | export {foo} from "foo"; 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/new-expression.js: -------------------------------------------------------------------------------- 1 | new X(); 2 | new Y()(); 3 | new F().z; 4 | 5 | new new x()(); 6 | new new x()(a); 7 | new new x(a)(); 8 | new new x(a)(a); 9 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/minified/no-semicolon.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | var x = 1; 3 | y(); 4 | if (bar) { 5 | baz(); 6 | } 7 | return; 8 | } 9 | 10 | function bar() { 11 | for(;;); 12 | } 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/arrow-function-object-body.js: -------------------------------------------------------------------------------- 1 | var foo = arr.map(v => ({ 2 | x: v.bar, 3 | y: v.bar*2 4 | })); 5 | var fn = () => ({}).key; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/arrow-function.js: -------------------------------------------------------------------------------- 1 | foo || (bar => bar()); 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/assignment-expression.js: -------------------------------------------------------------------------------- 1 | 1 + (a = 2); 2 | 1 + (a += 2); 3 | a = a || (a = {}); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/await-expression.js: -------------------------------------------------------------------------------- 1 | async function asdf() { 2 | (await 1) || (await 2); 3 | (await b)(); 4 | new (await b)(); 5 | true ? (await 1) : (await 2); 6 | await (await 1); 7 | } 8 | 9 | async function a(b) { 10 | (await xhr({ url: "views/test.html" })).data; 11 | } 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/expression.js: -------------------------------------------------------------------------------- 1 | a && (a.b && a.b.c()) && function() {}() && {a: 1}.a 2 | !function () {}(); 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/object.js: -------------------------------------------------------------------------------- 1 | ({}) === foo; 2 | ({}) && foo; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/sequence-expressions.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | return a, b; 3 | } 4 | 5 | if (a, b, c) d(); 6 | 7 | throw a, b, c; 8 | 9 | switch (a, b, c) {} 10 | 11 | for (a in b, c); 12 | 13 | while (a, b, c); 14 | 15 | !(function () {})(), a(); 16 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/terminator-break.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | return ( // foobar 3 | "bar" 4 | ); 5 | } 6 | 7 | function foo() { 8 | return ( 9 | // foobar 10 | "bar" 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/unary-arrow-function.js: -------------------------------------------------------------------------------- 1 | void (() => {}); 2 | typeof (() => {}); 3 | !(() => {}); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/parentheses/yield-expression.js: -------------------------------------------------------------------------------- 1 | function* asdf() { 2 | (yield 1) || (yield 2); 3 | (yield b)(); 4 | new (yield b)(); 5 | true ? (yield 1) : (yield 2); 6 | yield (yield 1); 7 | } 8 | 9 | function* a(b) { 10 | (yield xhr({ url: "views/test.html" })).data; 11 | } 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ArrayExpression-ArrayPattern.js: -------------------------------------------------------------------------------- 1 | [a, b, c]; 2 | [[], [b, c], []]; 3 | [a,, b,]; 4 | [a,,,, b]; 5 | [a, b,, c]; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ArrowFunctionExpression.js: -------------------------------------------------------------------------------- 1 | var foo = x => x * x; 2 | var foo = (a, b) => a * b; 3 | var foo = async x => x * x; 4 | var foo = async (a, b) => a * b; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/AssignmentExpression-BinaryExpression-LogicalExpression.js: -------------------------------------------------------------------------------- 1 | foo === bar; 2 | foo + bar; 3 | foo = bar; 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/AwaitExpression.js: -------------------------------------------------------------------------------- 1 | async function foo() { 2 | await bar(); 3 | } 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/BindExpression.js: -------------------------------------------------------------------------------- 1 | ::foo.bar.foo; 2 | ::foo.bar["foo"]; 3 | 4 | ctx::foo.bar.foo; 5 | ctx::foo.bar["foo"]; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/BlockStatement.js: -------------------------------------------------------------------------------- 1 | {} 2 | 3 | { 4 | foo(); 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/BreakStatement.js: -------------------------------------------------------------------------------- 1 | for (var i in foo) { 2 | break; 3 | } 4 | 5 | foo: for (var i in foo) { 6 | break foo; 7 | } 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/CallExpression.js: -------------------------------------------------------------------------------- 1 | foo(); 2 | foo("foo"); 3 | foo("foo", "bar"); 4 | foo(bar()); 5 | foo(bar("test")); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ClassBody-MethodDefinition.js: -------------------------------------------------------------------------------- 1 | class Foo { 2 | async foo() {} 3 | foo() {} 4 | ["foo"]() {} 5 | get foo() {} 6 | set foo(bar) {} 7 | 8 | static async foo() {} 9 | static foo() {} 10 | static ["foo"]() {} 11 | static get foo() {} 12 | static set foo(bar) {} 13 | } 14 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ClassDeclaration.js: -------------------------------------------------------------------------------- 1 | var foo = class Foo {}; 2 | var foo = class Foo extends Bar {}; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ClassExpression.js: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | class Foo extends Bar {} 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ConditionalExpression.js: -------------------------------------------------------------------------------- 1 | foo ? foo : bar; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ContinueStatement.js: -------------------------------------------------------------------------------- 1 | for (var i in foo) { 2 | continue; 3 | } 4 | 5 | foo: for (var i in foo) { 6 | continue foo; 7 | } 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/DebuggerStatement.js: -------------------------------------------------------------------------------- 1 | debugger; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/Decorator.js: -------------------------------------------------------------------------------- 1 | var obj = { 2 | @foo 3 | @bar 4 | foo: "bar", 5 | 6 | @foo 7 | @bar 8 | foo() {}, 9 | 10 | @foo 11 | get foo() {}, 12 | 13 | @bar 14 | set bar(foo) {} 15 | }; 16 | 17 | class Foo { 18 | @foo 19 | @bar 20 | foo() {} 21 | 22 | @foo 23 | @bar 24 | foo() {} 25 | 26 | @foo 27 | get foo() {} 28 | 29 | @bar 30 | set bar(foo) {} 31 | } 32 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/DoWhileStatement.js: -------------------------------------------------------------------------------- 1 | do { 2 | test(); 3 | } while (true); 4 | 5 | do {} while (true); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/EmptyStatement.js: -------------------------------------------------------------------------------- 1 | ; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ExportDefaultDeclaration-ExportSpecifier-ExportNamedDeclaration.js: -------------------------------------------------------------------------------- 1 | export default 42; 2 | export default {}; 3 | export default []; 4 | export default foo; 5 | export default function () {} 6 | export default class {} 7 | export default function foo() {} 8 | export default class Foo {} 9 | export * from "foo"; 10 | export * as foo from "foo"; 11 | export foo from "foo"; 12 | export * as foo, { bar } from "foo"; 13 | export foo, { bar } from "foo"; 14 | export { foo } from "foo"; 15 | export { foo, bar } from "foo"; 16 | export { foo as bar } from "foo"; 17 | export { foo as default } from "foo"; 18 | export { foo as default, bar } from "foo"; 19 | export { foo }; 20 | export { foo, bar }; 21 | export { foo as bar }; 22 | export { foo as default }; 23 | export { foo as default, bar }; 24 | export var foo = 1; 25 | export var foo2 = function () {}; 26 | export var foo3; 27 | export let foo4 = 2; 28 | export let foo5; 29 | export const foo6 = 3; 30 | export function foo7() {} 31 | export class foo8 {} 32 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ForInStatement.js: -------------------------------------------------------------------------------- 1 | for (var i in nums) {} 2 | 3 | for (var i in nums) { 4 | nums[i] = nums[i] * nums[i]; 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ForOfStatement.js: -------------------------------------------------------------------------------- 1 | for (var x of nums) {} 2 | 3 | for (var x of nums) { 4 | console.log(x * x); 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ForStatement.js: -------------------------------------------------------------------------------- 1 | for (var i = 0;;) {} 2 | for (var i = 0; i < 5;) {} 3 | for (var i = 0; i < 5; i++) {} 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/FunctionDeclaration-FunctionExpression.js: -------------------------------------------------------------------------------- 1 | function foo(bar = "bar") {} 2 | 3 | function foo(bar = "bar", ...items) {} 4 | 5 | function foo(...items) {} 6 | 7 | function* foo() {} 8 | 9 | function foo() {} 10 | 11 | async function foo() {} 12 | 13 | var foo = function* foo() {}; 14 | 15 | var foo = function foo() {}; 16 | 17 | var foo = async function foo() {}; 18 | 19 | var foo = function* () {}; 20 | 21 | var foo = function () {}; 22 | 23 | var foo = async function () {}; 24 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/Identifier.js: -------------------------------------------------------------------------------- 1 | foo; 2 | undefined; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/IfStatement.js: -------------------------------------------------------------------------------- 1 | if (foo) foobar(); 2 | 3 | if (foo) { 4 | foobar(); 5 | } 6 | 7 | if (foo) {} 8 | 9 | if (foo) { 10 | foo(); 11 | } else bar(); 12 | 13 | if (foo) { 14 | foo(); 15 | } else { 16 | bar(); 17 | } 18 | 19 | if (foo) { 20 | foo(); 21 | } else if (bar) { 22 | foobar(); 23 | } else { 24 | bar(); 25 | } 26 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ImportDeclaration-ImportSpecifier-ImportNamespaceSpecifier.js: -------------------------------------------------------------------------------- 1 | import "foo"; 2 | import foo from "foo"; 3 | import { default as foo } from "foo"; 4 | import * as foo from "foo"; 5 | import foo, { baz as xyz } from "foo"; 6 | import { bar } from "foo"; 7 | import { bar, baz } from "foo"; 8 | import { bar as baz } from "foo"; 9 | import { bar as baz, xyz } from "foo"; 10 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/LabeledStatement.js: -------------------------------------------------------------------------------- 1 | label: for (var i in test) {} 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/Literal.js: -------------------------------------------------------------------------------- 1 | 5; 2 | 5.0; 3 | "foobar"; 4 | "\n\r\u2028\u2029"; 5 | /foobar/g; 6 | null; 7 | true; 8 | false; 9 | 5.; 10 | 0b10; 11 | 0o70; 12 | 0X1F; 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/MemberExpression.js: -------------------------------------------------------------------------------- 1 | foo["bar"]; 2 | foo.bar; 3 | 4 | foo.bar.foo; 5 | foo.bar["foo"]; 6 | 7 | foo["foo"]["bar"]; 8 | foo[test()][bar()]; 9 | 10 | 0..toString(); 11 | 0.5.toString(); 12 | 1.0.toString(); 13 | 1.000.toString(); 14 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/NewExpression.js: -------------------------------------------------------------------------------- 1 | new Foo; 2 | new Foo(); 3 | new Foo(bar); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ObjectExpression-ObjectPattern-Property.js: -------------------------------------------------------------------------------- 1 | var foo = {}; 2 | 3 | var foo = { x, y }; 4 | 5 | var foo = { x: x, y: y }; 6 | 7 | var foo = { 8 | x: x, 9 | y: y 10 | }; 11 | 12 | var foo = { 13 | ["bar"]: "foo", 14 | ["foo"]() {}, 15 | foo() {}, 16 | async foo() {}, 17 | *foo() {}, 18 | get foo() {}, 19 | set foo(foo) {} 20 | }; 21 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ReturnStatement.js: -------------------------------------------------------------------------------- 1 | function foo() { 2 | return; 3 | } 4 | 5 | function bar() { 6 | return "foo"; 7 | } 8 | 9 | function foo() { 10 | return 1, "foo"; 11 | } 12 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/SequenceExpression.js: -------------------------------------------------------------------------------- 1 | foo, bar; 2 | 3 | foo, 4 | bar; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/SpreadElement-SpreadProperty.js: -------------------------------------------------------------------------------- 1 | [...foo]; 2 | foo(bar, ...items); 3 | new Foo(...foo); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/SwitchStatement-SwitchCase.js: -------------------------------------------------------------------------------- 1 | switch (foo) {} 2 | 3 | switch (foo) { 4 | case "foo": 5 | } 6 | 7 | switch (foo) { 8 | default: 9 | } 10 | 11 | switch (foo) { 12 | case "foo": 13 | default: 14 | } 15 | 16 | switch (foo) { 17 | case "foo": 18 | case "bar": 19 | default: 20 | } 21 | 22 | switch (foo) { 23 | case "foo": 24 | foo(); 25 | break; 26 | 27 | case "bar": 28 | bar(); 29 | break; 30 | 31 | default: 32 | yay(); 33 | } 34 | 35 | switch (foo) { 36 | case "foo": foo(); 37 | case "bar": bar(); 38 | default: yay(); 39 | } 40 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/TemplateLiteral-TaggedTemplateExpression-TemplateElement.js: -------------------------------------------------------------------------------- 1 | html``; 2 | 3 | `multi 4 | lines`; 5 | 6 | `test ${ interpolation } test`; 7 | 8 | `foob 9 | 10 | asdf 11 | awer 12 | erqer`; 13 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ThisExpression.js: -------------------------------------------------------------------------------- 1 | this; 2 | this.foo; 3 | this["foo"]; 4 | this.foo(); 5 | this["foo"](); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/ThrowStatement.js: -------------------------------------------------------------------------------- 1 | throw err; 2 | throw Error("foobar"); 3 | throw new Error("foobar"); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/TryStatement-CatchClause.js: -------------------------------------------------------------------------------- 1 | try {} catch (err) {} 2 | 3 | try { 4 | bar; 5 | } catch (err) {} 6 | 7 | try { 8 | bar; 9 | } catch (err) { 10 | foo(); 11 | } 12 | 13 | try { 14 | bar; 15 | } catch (err) { 16 | foo(); 17 | } finally { 18 | yay(); 19 | } 20 | 21 | try { 22 | bar; 23 | } catch (err) { 24 | foo(); 25 | } finally {} 26 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/UnaryExpression.js: -------------------------------------------------------------------------------- 1 | delete delete i; 2 | + +i; 3 | !!i; 4 | + ++i; 5 | - --i; 6 | typeof a(); 7 | (typeof a)(); 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/UpdateExpression.js: -------------------------------------------------------------------------------- 1 | ++i; 2 | i++; 3 | (foo++).test(); 4 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/VariableDeclaration-VariableDeclarator.js: -------------------------------------------------------------------------------- 1 | let foo; 2 | var foo; 3 | 4 | let foo = "foo"; 5 | var foo = "bar"; 6 | const foo = "foo"; 7 | 8 | let foo, bar = "bar"; 9 | var foo, bar = "bar"; 10 | 11 | let foo = "foo", bar = "bar"; 12 | var foo = "foo", bar = "bar"; 13 | const foo = "foo", bar = "bar"; 14 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/WhileStatement.js: -------------------------------------------------------------------------------- 1 | while (foo) {} 2 | 3 | while (foo) { 4 | bar(); 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/WithStatement.js: -------------------------------------------------------------------------------- 1 | with (foo) {} 2 | 3 | with (foo) { 4 | bar(); 5 | } 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSAttribute.js: -------------------------------------------------------------------------------- 1 |
; 2 | 3 |
text
; 4 | 5 |
; 6 | 7 |
text
; 8 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSElement-XJSOpeningElement-XJSClosingElement-XJSIdentifier.js: -------------------------------------------------------------------------------- 1 |
; 2 | 3 |
; 4 | 5 |
text
; 6 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSEmptyExpression.js: -------------------------------------------------------------------------------- 1 | {}; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSExpressionContainer.js: -------------------------------------------------------------------------------- 1 |
{this.props.children}
; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSMemberExpression.js: -------------------------------------------------------------------------------- 1 | ; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSNamespacedName.js: -------------------------------------------------------------------------------- 1 | ; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/XJSSpreadAttribute.js: -------------------------------------------------------------------------------- 1 | ; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/babel/types/YieldExpression.js: -------------------------------------------------------------------------------- 1 | function* foo() { 2 | yield bar; 3 | } 4 | 5 | function* bar() { 6 | yield* foo(); 7 | } 8 | -------------------------------------------------------------------------------- /src/__fixtures__/debug/foo: -------------------------------------------------------------------------------- 1 | function reasonablyLongFunctionName(apple: string, banana: number, red: string) {} 2 | -------------------------------------------------------------------------------- /src/__fixtures__/old/basics/simple-scope-breaking: -------------------------------------------------------------------------------- 1 | const foo = { 2 | meh: 'reasonably long value', 3 | meh2: 'this one will make things wrap, hopefully...', 4 | }; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/old/basics/variable-declarations: -------------------------------------------------------------------------------- 1 | var foo, bar; 2 | var baz; 3 | let buz = 1; 4 | const qux = { one: 1, two: 2 }; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/old/basics/works: -------------------------------------------------------------------------------- 1 | 1+1; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/old/comments/simple-block-comment: -------------------------------------------------------------------------------- 1 | /* 2 | * comment 3 | */ 4 | 1+1; 5 | -------------------------------------------------------------------------------- /src/__fixtures__/old/comments/simple-comment: -------------------------------------------------------------------------------- 1 | // This is a comment 2 | 1+1; 3 | -------------------------------------------------------------------------------- /src/__fixtures__/old/formatting/binary_expression_chains: -------------------------------------------------------------------------------- 1 | this_is_a_long_identifier + this_is_another_long_identifier - here_is_one_more_of_them + and_another; 2 | 3 | t(this_is_a_long_identifier + this_is_another_long_identifier - here_is_one_more_of_them + and_another); 4 | 5 | t(this_is_a_long_identifier + (this_is_another_long_identifier - here_is_one_more_of_them) + and_another); 6 | -------------------------------------------------------------------------------- /src/__fixtures__/old/formatting/breaks_function_calls: -------------------------------------------------------------------------------- 1 | fooo(one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve); 2 | foooo(one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve); 3 | -------------------------------------------------------------------------------- /src/__fixtures__/old/formatting/complex_conditionals: -------------------------------------------------------------------------------- 1 | foo ? bar : baz; 2 | this_is_a_long_identifier ? [with_some_array_elements, that_will_break] : [here, is, another, array_that_has_things]; 3 | this_is_a_long_identifier ? [this_array_is_also_really_long, so_it_will_also_need_to_break, independently_of_whether_or_not_the_conditional, needs_to_break] : [here, is, another, array_that_has_things, it_might_not, need_to_break]; 4 | -------------------------------------------------------------------------------- /src/__fixtures__/old/formatting/logical_expression_chains: -------------------------------------------------------------------------------- 1 | foo || bar && baz 2 | 3 | this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one; 4 | 5 | (this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one); 6 | 7 | this_is_a_naked_chain || of_logical_expressions || we_should_wrap_this || in_parenthesis_when_it_breaks; 8 | 9 | this_is_a_naked_chain || (these_are_some_ands && that_fit_on_one_line) || this_is_a_naked_chain_2; 10 | 11 | this_is_a_naked_chain || (these_are_some_ands && and_there_are_so_many && of_them_that_they_will_also && need_to_be_broken_up && after_the_first_chain) || this_is_a_naked_chain_2; 12 | 13 | if (this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one) { 14 | this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one; 15 | } 16 | 17 | (this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one)(); 18 | 19 | (this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one)(this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one); 20 | 21 | (this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one)((this_is_a_long_identifier || this_is_another_one && this_one_is_too || one_more_short_one)); 22 | 23 | foo( 24 | long_identifier_foo || 25 | long_identifier_foo || 26 | long_identifier_foo || 27 | bar( 28 | long_identifier_bar || 29 | long_identifier_bar || 30 | long_identifier_bar || 31 | baz( 32 | long_identifier_baz, 33 | long_identifier_baz, 34 | long_identifier_baz, 35 | buz( 36 | long_identifier_buz || 37 | long_identifier_buz || 38 | long_identifier_buz || 39 | long_identifier_buz || 40 | long_identifier_buz || 41 | long_identifier_buz 42 | ), 43 | long_identifier_baz, 44 | long_identifier_baz, 45 | long_identifier_baz, 46 | ) || 47 | long_identifier_bar || 48 | long_identifier_bar || 49 | long_identifier_bar 50 | ) || 51 | long_identifier_foo || 52 | long_identifier_foo || 53 | long_identifier_foo 54 | ); 55 | -------------------------------------------------------------------------------- /src/__fixtures__/old/integration/code_01: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | import comments from './printers/comments'; 10 | import expressions from './printers/expressions'; 11 | import literals from './printers/literals'; 12 | import misc from './printers/misc'; 13 | import statements from './printers/statements'; 14 | 15 | /** 16 | * Printers convert an AST into tokens which may then be formatted. 17 | */ 18 | export default function getPrinters(x, y, z) { 19 | return { 20 | ...comments, 21 | ...expressions, 22 | ...literals, 23 | ...misc, 24 | ...statements, 25 | ...thisissomethingreallylongthatwillbreak, 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /src/__fixtures__/old/integration/code_02: -------------------------------------------------------------------------------- 1 | x; 2 | // There should be no extra new lines in between these statements. 3 | x; 4 | -------------------------------------------------------------------------------- /src/__fixtures__/old/integration/flux_reduce_store: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 3 | * 4 | * This source code is licensed under the BSD-style license found in the 5 | * LICENSE file in the root directory of this source tree. An additional grant 6 | * of patent rights can be found in the PATENTS file in the same directory. 7 | * 8 | * @providesModule FluxReduceStore 9 | * @flow 10 | */ 11 | 12 | 'use strict'; 13 | 14 | import type Dispatcher from 'Dispatcher'; 15 | 16 | const FluxStore = require('FluxStore'); 17 | 18 | const abstractMethod = require('abstractMethod'); 19 | const invariant = require('invariant'); 20 | 21 | /** 22 | * This is the basic building block of a Flux application. All of your stores 23 | * should extend this class. 24 | * 25 | * class CounterStore extends FluxReduceStore { 26 | * getInitialState(): number { 27 | * return 1; 28 | * } 29 | * 30 | * reduce(state: number, action: Object): number { 31 | * switch(action.type) { 32 | * case: 'add': 33 | * return state + action.value; 34 | * case: 'double': 35 | * return state * 2; 36 | * default: 37 | * return state; 38 | * } 39 | * } 40 | * } 41 | */ 42 | class FluxReduceStore extends FluxStore { 43 | 44 | _state: TState; 45 | 46 | constructor(dispatcher: Dispatcher) { super(dispatcher); this._state = this.getInitialState(); } 47 | 48 | /** 49 | * Getter that exposes the entire state of this store. If your state is not 50 | * immutable you should override this and not expose _state directly. 51 | */ 52 | getState(): TState { return this._state; } 53 | 54 | /** 55 | * Constructs the initial state for this store. This is called once during 56 | * construction of the store. 57 | */ 58 | getInitialState(): TState { return abstractMethod('FluxReduceStore', 'getInitialState'); } 59 | 60 | /** 61 | * Used to reduce a stream of actions coming from the dispatcher into a 62 | * single state object. 63 | */ 64 | reduce(state: TState, action: Object): TState { return abstractMethod('FluxReduceStore', 'reduce'); } 65 | 66 | /** 67 | * Checks if two versions of state are the same. You do not need to override 68 | * this if your state is immutable. 69 | */ 70 | areEqual(one: TState, two: TState): boolean { return one === two; } 71 | 72 | __invokeOnDispatch(action: Object): void { 73 | this.__changed = false; 74 | 75 | // Reduce the stream of incoming actions to state, update when necessary. 76 | const startingState = this._state; const endingState = this.reduce(startingState, action); 77 | 78 | // This means your ending state should never be undefined. 79 | invariant(endingState !== undefined, '%s returned undefined from reduce(...), did you forget to return ' + 'state in the default case? (use null if this was intentional)', this.constructor.name); 80 | 81 | if (!this.areEqual(startingState, endingState)) { 82 | this._state = endingState; 83 | 84 | // `__emitChange()` sets `this.__changed` to true and then the actual 85 | // change will be fired from the emitter at the end of the dispatch, this 86 | // is required in order to support methods like `hasChanged()` 87 | this.__emitChange(); 88 | } 89 | 90 | if (this.__changed) { this.__emitter.emit(this.__changeEvent); } 91 | } 92 | } 93 | 94 | module.exports = FluxReduceStore; 95 | -------------------------------------------------------------------------------- /src/__fixtures__/old/literals/changes-quotes: -------------------------------------------------------------------------------- 1 | let x = 'foobar'; 2 | x = "foobar"; 3 | x = '"'; 4 | x = "\""; 5 | x = '\''; 6 | x = "'"; 7 | -------------------------------------------------------------------------------- /src/__fixtures__/old/literals/large-numbers: -------------------------------------------------------------------------------- 1 | 100000000000000000000123456789; 2 | -------------------------------------------------------------------------------- /src/__fixtures__/old/literals/string-escapes: -------------------------------------------------------------------------------- 1 | let x = '\\\\\\\''; 2 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/fjs_babel-test.js.snap: -------------------------------------------------------------------------------- 1 | exports[`test 2-space-multi-comment-with-space.js 1`] = ` 2 | "function test() { 3 | /* 4 | * this is comment 5 | */ 6 | 7 | 8 | var i = 20; 9 | } 10 | " 11 | `; 12 | 13 | exports[`test 2-space-multi-comment.js 1`] = ` 14 | "function test() { 15 | /* 16 | * this is comment 17 | */ 18 | var i = 20; 19 | } 20 | " 21 | `; 22 | 23 | exports[`test ArrayExpression-ArrayPattern.js 1`] = ` 24 | "[a, b, c]; 25 | [[], [b, c], []]; 26 | [a, , b]; 27 | [a, , , , b]; 28 | [a, b, , c]; 29 | " 30 | `; 31 | 32 | exports[`test AssignmentExpression-BinaryExpression-LogicalExpression.js 1`] = ` 33 | "foo === bar; 34 | foo + bar; 35 | foo = bar; 36 | " 37 | `; 38 | 39 | exports[`test BlockStatement.js 1`] = ` 40 | "{} 41 | { 42 | foo(); 43 | } 44 | " 45 | `; 46 | 47 | exports[`test CallExpression.js 1`] = ` 48 | "foo(); 49 | foo(\'foo\'); 50 | foo(\'foo\', \'bar\'); 51 | foo(bar()); 52 | foo(bar(\'test\')); 53 | " 54 | `; 55 | 56 | exports[`test ConditionalExpression.js 1`] = ` 57 | "foo ? foo : bar; 58 | " 59 | `; 60 | 61 | exports[`test DebuggerStatement.js 1`] = ` 62 | "debugger; 63 | " 64 | `; 65 | 66 | exports[`test EmptyStatement.js 1`] = ` 67 | "; 68 | " 69 | `; 70 | 71 | exports[`test Identifier.js 1`] = ` 72 | "foo; 73 | undefined; 74 | " 75 | `; 76 | 77 | exports[`test IfStatement.js 1`] = ` 78 | "if (foo) foobar(); 79 | 80 | if (foo) { 81 | foobar(); 82 | } 83 | 84 | if (foo) {} 85 | 86 | if (foo) { 87 | foo(); 88 | } else bar(); 89 | 90 | if (foo) { 91 | foo(); 92 | } else { 93 | bar(); 94 | } 95 | if (foo) { 96 | foo(); 97 | } else if (bar) { 98 | foobar(); 99 | } else { 100 | bar(); 101 | } 102 | " 103 | `; 104 | 105 | exports[`test Literal.js 1`] = ` 106 | "5; 107 | 5.0; 108 | \'foobar\'; 109 | \'\\n\\r

\'; 110 | /foobar/g; 111 | null; 112 | true; 113 | false; 114 | 5.; 115 | 0b10; 116 | 0o70; 117 | 0X1F; 118 | " 119 | `; 120 | 121 | exports[`test MemberExpression.js 1`] = ` 122 | "foo[\'bar\']; 123 | foo.bar; 124 | 125 | foo.bar.foo; 126 | foo.bar[\'foo\']; 127 | 128 | foo[\'foo\'][\'bar\']; 129 | foo[test()][bar()]; 130 | 131 | 0..toString(); 132 | 0.5.toString(); 133 | 1.0.toString(); 134 | 1.000.toString(); 135 | " 136 | `; 137 | 138 | exports[`test ObjectExpression-ObjectPattern-Property.js 1`] = ` 139 | "var foo = {}; 140 | 141 | var foo = { x, y }; 142 | 143 | var foo = { x: x, y: y }; 144 | 145 | var foo = { x: x, y: y }; 146 | 147 | var foo = { 148 | [\'bar\']: \'foo\', 149 | [\'foo\']() {}, 150 | foo() {}, 151 | async foo() {}, 152 | *foo() {}, 153 | get foo() {}, 154 | set foo(foo) {}, 155 | }; 156 | " 157 | `; 158 | 159 | exports[`test ThisExpression.js 1`] = ` 160 | "this; 161 | this.foo; 162 | this[\'foo\']; 163 | this.foo(); 164 | this[\'foo\'](); 165 | " 166 | `; 167 | 168 | exports[`test UpdateExpression.js 1`] = ` 169 | "++i; 170 | i++; 171 | foo++.test(); 172 | " 173 | `; 174 | 175 | exports[`test XJSAttribute.js 1`] = ` 176 | "
; 177 | 178 |
text
; 179 | 180 |
; 181 | 182 |
text
; 183 | " 184 | `; 185 | 186 | exports[`test XJSElement-XJSOpeningElement-XJSClosingElement-XJSIdentifier.js 1`] = ` 187 | "
; 188 | 189 |
; 190 | 191 |
text
; 192 | " 193 | `; 194 | 195 | exports[`test XJSEmptyExpression.js 1`] = ` 196 | "{}; 197 | " 198 | `; 199 | 200 | exports[`test XJSExpressionContainer.js 1`] = ` 201 | "
{this.props.children}
; 202 | " 203 | `; 204 | 205 | exports[`test XJSMemberExpression.js 1`] = ` 206 | "; 207 | " 208 | `; 209 | 210 | exports[`test XJSNamespacedName.js 1`] = ` 211 | "; 212 | " 213 | `; 214 | 215 | exports[`test XJSSpreadAttribute.js 1`] = ` 216 | "; 217 | " 218 | `; 219 | 220 | exports[`test assignment-expression.js 1`] = ` 221 | "1 + a = 2; 222 | 1 + a = 2; 223 | a = a || a = {}; 224 | " 225 | `; 226 | 227 | exports[`test assignment.js 1`] = ` 228 | "x = 1; 229 | var { y = 1 } = obj; 230 | " 231 | `; 232 | 233 | exports[`test binary-expressions.js 1`] = ` 234 | "1 * 1; 235 | 1 && 1; 236 | 1 + +1; 237 | x + ++y; 238 | (a + +b * 2); 239 | a + +b * 2 * 2 * 2; 240 | a - -b; 241 | 1 + -b; 242 | 1 - --b; 243 | a - -b * 2; 244 | 1 - --t * t; 245 | " 246 | `; 247 | 248 | exports[`test bitwise-precedence.js 1`] = ` 249 | "x | y ^ z; 250 | x | (y ^ z); 251 | (x | y) ^ z; 252 | " 253 | `; 254 | 255 | exports[`test block-line-comment-with-concise-format.js 1`] = ` 256 | "{ 257 | print(\'hello\'); 258 | } 259 | " 260 | `; 261 | 262 | exports[`test block-line-comment-with-retainlines-option.js 1`] = ` 263 | "{ 264 | print(\'hello\'); 265 | } 266 | " 267 | `; 268 | 269 | exports[`test block-line-comment.js 1`] = ` 270 | "// Leading to block 271 | { 272 | print(\'hello\'); 273 | } 274 | " 275 | `; 276 | 277 | exports[`test block-statements.js 1`] = ` 278 | "if (true) { 279 | foo; 280 | bar2; 281 | } else { 282 | foo; 283 | bar2; 284 | } 285 | function fn() { 286 | foo; 287 | bar2; 288 | } 289 | " 290 | `; 291 | 292 | exports[`test boolean-literal-types.js 1`] = ` 293 | "var foo: true; 294 | var bar: false; 295 | " 296 | `; 297 | 298 | exports[`test class-declaration.js 1`] = ` 299 | "class Test { 300 | } 301 | class Derived extends Super { 302 | } 303 | class StaticMethods { 304 | static n1() {} 305 | 306 | static get1() {} 307 | 308 | static set1(value) {} 309 | 310 | static gen1() {} 311 | } 312 | class Methods { 313 | n2() {} 314 | 315 | get2() {} 316 | 317 | set2(value) {} 318 | 319 | gen1() {} 320 | } 321 | class ComputedStaticMethods { 322 | static n1() {} 323 | 324 | static get1() {} 325 | 326 | static set1(value) {} 327 | 328 | static gen1() {} 329 | } 330 | class ComputedMethods { 331 | n2() {} 332 | 333 | get2() {} 334 | 335 | set2(value) {} 336 | 337 | gen1() {} 338 | } 339 | " 340 | `; 341 | 342 | exports[`test comment-only-with-space.js 1`] = ` 343 | " 344 | " 345 | `; 346 | 347 | exports[`test comment-only.js 1`] = ` 348 | " 349 | " 350 | `; 351 | 352 | exports[`test comment-statement-with-retainlines-option.js 1`] = ` 353 | "// comment 354 | print(\'hello\'); 355 | 356 | // comment2 357 | print(\'hello2\'); 358 | " 359 | `; 360 | 361 | exports[`test computed-property-comments-2.js 1`] = ` 362 | "var test = { /** 363 | * Before bracket init 364 | */ 365 | [\'a\']: \'1\', [/* 366 | * Inside bracket init 367 | */ 368 | \'b\']: \'2\' }, ok = 42; 369 | " 370 | `; 371 | 372 | exports[`test computed-property-comments.js 1`] = ` 373 | "var test = { 374 | /** 375 | * Before bracket init 376 | */ 377 | [\'a\']: \'1\', 378 | [/* 379 | * Inside bracket init 380 | */ 381 | \'b\']: \'2\', 382 | [\'c\']: /* 383 | * After bracket key 384 | */\'3\', 385 | // Before bracket, line comment 386 | [\'d\']: \'4\', 387 | [// Inside bracket, line comment 388 | \'e\']: \'5\', 389 | [\'f\']: // After bracket, line comment 390 | \'6\', 391 | }; 392 | " 393 | `; 394 | 395 | exports[`test double.js 1`] = ` 396 | "foo(\'foo\'); 397 | foo(\'foo\\nlol\'); 398 | foo(\'foo\\n\"lol\'); 399 | foo(\'foo\\n\"\\\'lol\'); 400 | foo(\'😂\'); 401 | " 402 | `; 403 | 404 | exports[`test empty-line-comment.js 1`] = ` 405 | "function test() { 406 | // Leading to EmptyStatement 407 | ; 408 | } 409 | " 410 | `; 411 | 412 | exports[`test empty.js 1`] = ` 413 | " 414 | " 415 | `; 416 | 417 | exports[`test export-default-declaration.js 1`] = ` 418 | "export default function a() {} 419 | " 420 | `; 421 | 422 | exports[`test floating-point.js 1`] = ` 423 | "1.1.valueOf(); 424 | 1e+300.valueOf(); 425 | " 426 | `; 427 | 428 | exports[`test hard-tab.js 1`] = ` 429 | "function foo() { 430 | bar(); 431 | if (foo) { 432 | bar(); 433 | } 434 | } 435 | " 436 | `; 437 | 438 | exports[`test if-block-line-comment.js 1`] = ` 439 | "if (cond) // Leading to if-block 440 | { 441 | print(\'hello\'); 442 | } 443 | " 444 | `; 445 | 446 | exports[`test if-empty-line-comment.js 1`] = ` 447 | "if (cond) // Leading to EmptyStatement 448 | ; 449 | " 450 | `; 451 | 452 | exports[`test if-line-comment.js 1`] = ` 453 | "function test() { 454 | // Leading if statement 455 | if (cond) { 456 | print(\'hello\'); 457 | } 458 | } 459 | " 460 | `; 461 | 462 | exports[`test jsx.js 1`] = ` 463 | "var single = \'quotes\'; 464 | var outnumber = \'double\'; 465 | var moreSingleQuotesThanDouble = \'!\'; 466 | 467 | React.createClass({ render() { 468 | return ; 472 | } }); 473 | " 474 | `; 475 | 476 | exports[`test labeled-statement.js 1`] = ` 477 | "function x() { 478 | return -1; 479 | return --i; 480 | return !2; 481 | return void0; 482 | } 483 | throw -1; 484 | " 485 | `; 486 | 487 | exports[`test literals.js 1`] = ` 488 | "5; 489 | 5.0; 490 | \'foobar\'; 491 | \' \'; 492 | \'\\n\\r\'; 493 | \'😂\'; 494 | /foobar/g; 495 | null; 496 | true; 497 | false; 498 | 5.; 499 | 0b10; 500 | 0o70; 501 | 0X1F; 502 | " 503 | `; 504 | 505 | exports[`test member-expression-numeric-literals.js 1`] = ` 506 | "1..toString; 507 | 2..toString(); 508 | 0x1F7.toString(); 509 | 0b111110111.toString(); 510 | 0o767.toString(); 511 | " 512 | `; 513 | 514 | exports[`test modules.js 1`] = ` 515 | "import from \'foo\'; 516 | import , from \'foo\'; 517 | import from \'foo\'; 518 | 519 | 520 | " 521 | `; 522 | 523 | exports[`test number-literal-types.js 1`] = ` 524 | "var a: 123; 525 | var a: 123.0; 526 | var a: 0x7B; 527 | var a: 0b1111011; 528 | var a: 0o173; 529 | " 530 | `; 531 | 532 | exports[`test object.js 1`] = ` 533 | "{} === foo; 534 | {} && foo; 535 | " 536 | `; 537 | 538 | exports[`test object_comments.js 1`] = ` 539 | "var test = { /** 540 | * Test 2 541 | */ 542 | a: \'1\', /* 543 | * Test 1 544 | */ 545 | b: \'2\', // Test 3 546 | c: \'3\' }; 547 | " 548 | `; 549 | 550 | exports[`test return-with-retainlines-and-compact-option.js 1`] = ` 551 | "function foo(l) { 552 | return // hi 553 | l; 554 | } 555 | " 556 | `; 557 | 558 | exports[`test return-with-retainlines-option.js 1`] = ` 559 | "function foo(l) { 560 | return l; 561 | } 562 | function foo() { 563 | return (1 && 2) || 3; 564 | } 565 | " 566 | `; 567 | 568 | exports[`test simple-a-lot-of-line-comment.js 1`] = ` 569 | "// Copyright (C) 2012 Yusuke Suzuki 570 | // 571 | // Redistribution and use in source and binary forms, with or without 572 | // modification, are permitted provided that the following conditions are met: 573 | // 574 | // * Redistributions of source code must retain the above copyright 575 | // notice, this list of conditions and the following disclaimer. 576 | // * Redistributions in binary form must reproduce the above copyright 577 | // notice, this list of conditions and the following disclaimer in the 578 | // documentation and/or other materials provided with the distribution. 579 | // 580 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" 581 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 582 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 583 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 584 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 585 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 586 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 587 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 588 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 589 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 590 | 591 | 592 | function test() {} 593 | " 594 | `; 595 | 596 | exports[`test simple-a-lot-of-multi-comment.js 1`] = ` 597 | "/* 598 | Copyright (C) 2012 Yusuke Suzuki 599 | 600 | Redistribution and use in source and binary forms, with or without 601 | modification, are permitted provided that the following conditions are met: 602 | 603 | * Redistributions of source code must retain the above copyright 604 | notice, this list of conditions and the following disclaimer. 605 | * Redistributions in binary form must reproduce the above copyright 606 | notice, this list of conditions and the following disclaimer in the 607 | documentation and/or other materials provided with the distribution. 608 | 609 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" 610 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 611 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 612 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 613 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 614 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 615 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 616 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 617 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 618 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 619 | */ 620 | 621 | function test() {} 622 | " 623 | `; 624 | 625 | exports[`test simple-line-comment.js 1`] = ` 626 | "// Leading 627 | var i = 20; 628 | " 629 | `; 630 | 631 | exports[`test simple-multi-comment.js 1`] = ` 632 | "function test() { 633 | /* 634 | * Leading comment 635 | */ 636 | 637 | /* 638 | * 639 | * Leading comment 2 640 | * 641 | */ 642 | 643 | var i = 20; 644 | } 645 | " 646 | `; 647 | 648 | exports[`test simple-statement-comment.js 1`] = ` 649 | "; 650 | " 651 | `; 652 | 653 | exports[`test single-line-comment.js 1`] = ` 654 | "// foo 655 | bar(); 656 | " 657 | `; 658 | 659 | exports[`test single.js 1`] = ` 660 | "foo(\'foo\'); 661 | foo(\'foo\\nlol\'); 662 | foo(\'foo\\n\"lol\'); 663 | foo(\'foo\\n\"\\\'lol\'); 664 | foo(\'😂\'); 665 | " 666 | `; 667 | 668 | exports[`test soft-tab-2.js 1`] = ` 669 | "function foo() { 670 | bar(); 671 | if (foo) { 672 | bar(); 673 | } 674 | } 675 | " 676 | `; 677 | 678 | exports[`test soft-tab-4.js 1`] = ` 679 | "function foo() { 680 | bar(); 681 | if (foo) { 682 | bar(); 683 | } 684 | } 685 | " 686 | `; 687 | 688 | exports[`test string-literal-types.js 1`] = ` 689 | "function createElement( 690 | tagName: \'div\', 691 | ) {}function createElement(tagName: \'div\') {} 692 | " 693 | `; 694 | 695 | exports[`test terminator-break.js 1`] = ` 696 | "function foo() { 697 | return // foobar 698 | \'bar\'; 699 | } 700 | function foo() { 701 | return // foobar 702 | \'bar\'; 703 | } 704 | " 705 | `; 706 | 707 | exports[`test this-types.js 1`] = ` 708 | "class Foo { 709 | bar(): this { 710 | return this; 711 | } 712 | } 713 | " 714 | `; 715 | 716 | exports[`test tuples.js 1`] = ` 717 | "var a: [] = []; 718 | var a: [Foo] = [foo]; 719 | var a: [number] = [123]; 720 | var a: [number, string] = [123, \'duck\']; 721 | " 722 | `; 723 | 724 | exports[`test variable-declarator-line-comment.js 1`] = ` 725 | "function test() { 726 | var // Leading to VariableDeclarator 727 | // Leading to VariableDeclarator 728 | i = 20, // Leading to VariableDeclarator 729 | // Leading to VariableDeclarator 730 | j = 20; 731 | } 732 | " 733 | `; 734 | 735 | exports[`test variable-declarator-multi-comment.js 1`] = ` 736 | "function test() { 737 | var /* 738 | * Leading to VariableDeclarator 739 | * Leading to VariableDeclarator 740 | */ 741 | i = 20, /* 742 | * Leading to VariableDeclarator 743 | * Leading to VariableDeclarator 744 | */ 745 | j = 20; 746 | } 747 | " 748 | `; 749 | 750 | exports[`test variable-declarator-trailing-comment.js 1`] = ` 751 | "{ 752 | var t = 20; 753 | } 754 | { 755 | var tt = 20; 756 | }{ 757 | { 758 | var t = 20; 759 | } 760 | } 761 | " 762 | `; 763 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/fjs_debug-test.js.snap: -------------------------------------------------------------------------------- 1 | exports[`test foo 1`] = ` 2 | "function reasonablyLongFunctionName( 3 | apple: string, 4 | banana: number, 5 | red: string, 6 | ) {} 7 | " 8 | `; 9 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/fjs_old-test.js.snap: -------------------------------------------------------------------------------- 1 | exports[`test binary_expression_chains 1`] = ` 2 | " 3 | this_is_a_long_identifier + 4 | this_is_another_long_identifier - 5 | here_is_one_more_of_them + 6 | and_another; 7 | 8 | t( 9 | this_is_a_long_identifier + 10 | this_is_another_long_identifier - 11 | here_is_one_more_of_them + 12 | and_another); 13 | 14 | t( 15 | this_is_a_long_identifier + 16 | (this_is_another_long_identifier - here_is_one_more_of_them) + 17 | and_another); 18 | " 19 | `; 20 | 21 | exports[`test breaks_function_calls 1`] = ` 22 | "fooo(one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve); 23 | foooo( 24 | one, 25 | two, 26 | three, 27 | four, 28 | five, 29 | six, 30 | seven, 31 | eight, 32 | nine, 33 | ten, 34 | eleven, 35 | twelve, 36 | ); 37 | " 38 | `; 39 | 40 | exports[`test changes-quotes 1`] = ` 41 | "let x = \'foobar\'; 42 | x = \'foobar\'; 43 | x = \'\"\'; 44 | x = \'\"\'; 45 | x = \'\\\'\'; 46 | x = \'\\\'\'; 47 | " 48 | `; 49 | 50 | exports[`test code_01 1`] = ` 51 | "/** 52 | * Copyright 2004-present Facebook. All Rights Reserved. 53 | */ 54 | 55 | \'use strict\'; 56 | 57 | import Tokens from \'./Tokens\'; 58 | 59 | import comments from \'./printers/comments\'; 60 | import expressions from \'./printers/expressions\'; 61 | import literals from \'./printers/literals\'; 62 | import misc from \'./printers/misc\'; 63 | import statements from \'./printers/statements\'; 64 | 65 | /** 66 | * Printers convert an AST into tokens which may then be formatted. 67 | */ 68 | export default function getPrinters(x, y, z) { 69 | return { 70 | ...comments, 71 | ...expressions, 72 | ...literals, 73 | ...misc, 74 | ...statements, 75 | ...thisissomethingreallylongthatwillbreak, 76 | }; 77 | }; 78 | " 79 | `; 80 | 81 | exports[`test code_02 1`] = ` 82 | "x; 83 | // There should be no extra new lines in between these statements. 84 | x; 85 | " 86 | `; 87 | 88 | exports[`test complex_conditionals 1`] = ` 89 | "foo ? bar : baz; 90 | this_is_a_long_identifier 91 | ? [with_some_array_elements, that_will_break] 92 | : [here, is, another, array_that_has_things]; 93 | this_is_a_long_identifier 94 | ? [ 95 | this_array_is_also_really_long, 96 | so_it_will_also_need_to_break, 97 | independently_of_whether_or_not_the_conditional, 98 | needs_to_break, 99 | ] 100 | : [here, is, another, array_that_has_things, it_might_not, need_to_break]; 101 | " 102 | `; 103 | 104 | exports[`test flux_reduce_store 1`] = ` 105 | "/** 106 | * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 107 | * 108 | * This source code is licensed under the BSD-style license found in the 109 | * LICENSE file in the root directory of this source tree. An additional grant 110 | * of patent rights can be found in the PATENTS file in the same directory. 111 | * 112 | * @providesModule FluxReduceStore 113 | * @flow 114 | */ 115 | 116 | \'use strict\'; 117 | 118 | import Dispatcher from \'Dispatcher\'; 119 | 120 | const FluxStore = require(\'FluxStore\'); 121 | 122 | const abstractMethod = require(\'abstractMethod\'); 123 | const invariant = require(\'invariant\'); 124 | 125 | /** 126 | * This is the basic building block of a Flux application. All of your stores 127 | * should extend this class. 128 | * 129 | * class CounterStore extends FluxReduceStore { 130 | * getInitialState(): number { 131 | * return 1; 132 | * } 133 | * 134 | * reduce(state: number, action: Object): number { 135 | * switch(action.type) { 136 | * case: \'add\': 137 | * return state + action.value; 138 | * case: \'double\': 139 | * return state * 2; 140 | * default: 141 | * return state; 142 | * } 143 | * } 144 | * } 145 | */ 146 | class FluxReduceStore extends FluxStore { 147 | _state: TState; 148 | 149 | constructor(dispatcher: Dispatcher) { 150 | super(dispatcher); 151 | this._state = this.getInitialState(); 152 | } 153 | 154 | /** 155 | * Getter that exposes the entire state of this store. If your state is not 156 | * immutable you should override this and not expose _state directly. 157 | */ 158 | getState(): TState { 159 | return this._state; 160 | } 161 | 162 | /** 163 | * Constructs the initial state for this store. This is called once during 164 | * construction of the store. 165 | */ 166 | getInitialState(): TState { 167 | return abstractMethod(\'FluxReduceStore\', \'getInitialState\'); 168 | } 169 | 170 | /** 171 | * Used to reduce a stream of actions coming from the dispatcher into a 172 | * single state object. 173 | */ 174 | reduce(state: TState, action: Object): TState { 175 | return abstractMethod(\'FluxReduceStore\', \'reduce\'); 176 | } 177 | 178 | /** 179 | * Checks if two versions of state are the same. You do not need to override 180 | * this if your state is immutable. 181 | */ 182 | areEqual(one: TState, two: TState): boolean { 183 | return one === two; 184 | } 185 | 186 | __invokeOnDispatch(action: Object): void { 187 | this.__changed = false; 188 | 189 | // Reduce the stream of incoming actions to state, update when necessary. 190 | const startingState = this._state; 191 | const endingState = this.reduce(startingState, action); 192 | 193 | // This means your ending state should never be undefined. 194 | invariant( 195 | endingState !== undefined, 196 | \'%s returned undefined from reduce(...), did you forget to return \' + 197 | \'state in the default case? (use null if this was intentional)\', 198 | this.constructor.name, 199 | ); 200 | 201 | if (!this.areEqual(startingState, endingState)) { 202 | this._state = endingState; 203 | 204 | // \`__emitChange()\` sets \`this.__changed\` to true and then the actual 205 | // change will be fired from the emitter at the end of the dispatch, this 206 | // is required in order to support methods like \`hasChanged()\` 207 | this.__emitChange(); 208 | } 209 | 210 | if (this.__changed) { 211 | this.__emitter.emit(this.__changeEvent); 212 | } 213 | } 214 | } 215 | 216 | module.exports = FluxReduceStore; 217 | " 218 | `; 219 | 220 | exports[`test large-numbers 1`] = ` 221 | "100000000000000000000123456789; 222 | " 223 | `; 224 | 225 | exports[`test logical_expression_chains 1`] = ` 226 | "foo || bar && baz; 227 | 228 | ( 229 | this_is_a_long_identifier || 230 | this_is_another_one && 231 | this_one_is_too || 232 | one_more_short_one 233 | ); 234 | 235 | ( 236 | this_is_a_long_identifier || 237 | this_is_another_one && 238 | this_one_is_too || 239 | one_more_short_one 240 | ); 241 | 242 | ( 243 | this_is_a_naked_chain || 244 | of_logical_expressions || 245 | we_should_wrap_this || 246 | in_parenthesis_when_it_breaks 247 | ); 248 | 249 | ( 250 | this_is_a_naked_chain || 251 | (these_are_some_ands && that_fit_on_one_line) || 252 | this_is_a_naked_chain_2 253 | ); 254 | 255 | this_is_a_naked_chain || ( 256 | these_are_some_ands && 257 | and_there_are_so_many && 258 | of_them_that_they_will_also && 259 | need_to_be_broken_up && 260 | after_the_first_chain 261 | ) || this_is_a_naked_chain_2; 262 | 263 | if ( 264 | this_is_a_long_identifier || 265 | this_is_another_one && 266 | this_one_is_too || 267 | one_more_short_one 268 | ) { 269 | ( 270 | this_is_a_long_identifier || 271 | this_is_another_one && 272 | this_one_is_too || 273 | one_more_short_one 274 | ); 275 | } 276 | 277 | ( 278 | this_is_a_long_identifier || 279 | this_is_another_one && 280 | this_one_is_too || 281 | one_more_short_one 282 | )(); 283 | 284 | ( 285 | this_is_a_long_identifier || 286 | this_is_another_one && 287 | this_one_is_too || 288 | one_more_short_one 289 | )( 290 | this_is_a_long_identifier || 291 | this_is_another_one && 292 | this_one_is_too || 293 | one_more_short_one 294 | ); 295 | 296 | ( 297 | this_is_a_long_identifier || 298 | this_is_another_one && 299 | this_one_is_too || 300 | one_more_short_one 301 | )(( 302 | this_is_a_long_identifier || 303 | this_is_another_one && 304 | this_one_is_too || 305 | one_more_short_one 306 | )); 307 | 308 | foo( 309 | long_identifier_foo || 310 | long_identifier_foo || 311 | long_identifier_foo || 312 | bar( 313 | long_identifier_bar || 314 | long_identifier_bar || 315 | long_identifier_bar || 316 | baz(long_identifier_baz, long_identifier_baz, long_identifier_baz, buz( 317 | long_identifier_buz || 318 | long_identifier_buz || 319 | long_identifier_buz || 320 | long_identifier_buz || 321 | long_identifier_buz || 322 | long_identifier_buz, 323 | ), long_identifier_baz, long_identifier_baz, long_identifier_baz) || 324 | long_identifier_bar || 325 | long_identifier_bar || 326 | long_identifier_bar, 327 | ) || 328 | long_identifier_foo || 329 | long_identifier_foo || 330 | long_identifier_foo 331 | ); 332 | " 333 | `; 334 | 335 | exports[`test simple-block-comment 1`] = ` 336 | "/* 337 | * comment 338 | */ 339 | 1 + 1; 340 | " 341 | `; 342 | 343 | exports[`test simple-comment 1`] = ` 344 | "// This is a comment 345 | 1 + 1; 346 | " 347 | `; 348 | 349 | exports[`test simple-scope-breaking 1`] = ` 350 | "const foo = { 351 | meh: \'reasonably long value\', 352 | meh2: \'this one will make things wrap, hopefully...\', 353 | }; 354 | " 355 | `; 356 | 357 | exports[`test string-escapes 1`] = ` 358 | "let x = \'\\\\\\\\\\\\\\\'\'; 359 | " 360 | `; 361 | 362 | exports[`test variable-declarations 1`] = ` 363 | "var foo, bar; 364 | var baz; 365 | let buz = 1; 366 | const qux = { one: 1, two: 2 }; 367 | " 368 | `; 369 | 370 | exports[`test works 1`] = ` 371 | "1 + 1; 372 | " 373 | `; 374 | -------------------------------------------------------------------------------- /src/__tests__/fjs_babel-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import testFixtures from '../testFixtures'; 8 | 9 | // Copied all the tests with something like this: (had to create directories first though) 10 | // find ~/dev/babel/packages/babel-generator/test/fixtures -name "actual.js" -exec bash -c 'cp "$1" $(echo "$1" | sed "s/\/actual//g" | sed -E "s/\/.*\/(.*)\//.\/\\1\//g")' -- {} \; 11 | testFixtures('babel', new Set([ 12 | 'do-while-line-comment.js', 13 | 'function-block-line-comment.js', 14 | 'return-no-argument.js', 15 | 'try-block-line-comment.js', 16 | 'while.js', 17 | 'for-in-no-in.js', 18 | 'for-loop-in.js', 19 | 'new-precedence.js', 20 | 'one-property-with-line-terminator.js', 21 | 'unary-op.js', 22 | 'variable-declaration.js', 23 | 'array-types.js', 24 | 'call-properties.js', 25 | 'declare-module.js', 26 | 'declare-statements.js', 27 | 'def-site-variance.js', 28 | 'interfaces-module-and-script.js', 29 | 'null-literal-types.js', 30 | 'qualified-generic-type.js', 31 | 'type-alias.js', 32 | 'type-annotations.js', 33 | 'type-parameters.js', 34 | 'typecasts.js', 35 | 'arrow-function.js', 36 | 'class-expression.js', 37 | 'computed-property.js', 38 | 'default-parameter.js', 39 | 'destructuring-assignment.js', 40 | 'exports.js', 41 | 'for-of-statement.js', 42 | 'import-with-default.js', 43 | 'imports.js', 44 | 'spread-element.js', 45 | 'templates-escape.js', 46 | 'templates-indentation.js', 47 | 'templates.js', 48 | 'yield-precedence.js', 49 | 'arrow-functions.js', 50 | 'new-expression.js', 51 | 'no-semicolon.js', 52 | 'arrow-function-object-body.js', 53 | 'arrow-function.js', 54 | 'await-expression.js', 55 | 'expression.js', 56 | 'sequence-expressions.js', 57 | 'unary-arrow-function.js', 58 | 'yield-expression.js', 59 | 'ArrowFunctionExpression.js', 60 | 'AwaitExpression.js', 61 | 'BindExpression.js', 62 | 'BreakStatement.js', 63 | 'ClassBody-MethodDefinition.js', 64 | 'ClassDeclaration.js', 65 | 'ClassExpression.js', 66 | 'ContinueStatement.js', 67 | 'Decorator.js', 68 | 'DoWhileStatement.js', 69 | 'ExportDefaultDeclaration-ExportSpecifier-ExportNamedDeclaration.js', 70 | 'ForInStatement.js', 71 | 'ForOfStatement.js', 72 | 'ForStatement.js', 73 | 'FunctionDeclaration-FunctionExpression.js', 74 | 'ImportDeclaration-ImportSpecifier-ImportNamespaceSpecifier.js', 75 | 'LabeledStatement.js', 76 | 'NewExpression.js', 77 | 'ReturnStatement.js', 78 | 'SequenceExpression.js', 79 | 'SpreadElement-SpreadProperty.js', 80 | 'SwitchStatement-SwitchCase.js', 81 | 'TemplateLiteral-TaggedTemplateExpression-TemplateElement.js', 82 | 'ThrowStatement.js', 83 | 'TryStatement-CatchClause.js', 84 | 'UnaryExpression.js', 85 | 'VariableDeclaration-VariableDeclarator.js', 86 | 'WhileStatement.js', 87 | 'WithStatement.js', 88 | 'YieldExpression.js', 89 | ])); 90 | -------------------------------------------------------------------------------- /src/__tests__/fjs_debug-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import testFixtures from '../testFixtures'; 8 | 9 | testFixtures('debug'); 10 | -------------------------------------------------------------------------------- /src/__tests__/fjs_old-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import testFixtures from '../testFixtures'; 8 | 9 | testFixtures('old'); 10 | -------------------------------------------------------------------------------- /src/__tests__/missing_printers-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | jest.autoMockOff(); 6 | 7 | import {VISITOR_KEYS} from 'babel-types'; 8 | 9 | import getPrinters from '../getPrinters'; 10 | 11 | /** 12 | * These are printers for nodes that aren't really part of the AST. At least, 13 | * babel doesn't include them in VISITOR_KEYS. 14 | */ 15 | const EXTRA_PRINTERS = new Set([ 16 | 'CommentBlock', 17 | 'CommentLine', 18 | ]); 19 | 20 | /** 21 | * These are the nodes we have not yet implemented. As printers are added for 22 | * these the test will throw an error if they are not removed here. 23 | */ 24 | const UNIMPLEMENTED = new Set([ 25 | 'ArrowFunctionExpression', 26 | 'CatchClause', 27 | 'ClassExpression', 28 | 'ClassImplements', 29 | 'DeclareClass', 30 | 'DeclareFunction', 31 | 'DeclareInterface', 32 | 'DeclareModule', 33 | 'DeclareTypeAlias', 34 | 'DeclareVariable', 35 | 'Decorator', 36 | 'DoExpression', 37 | 'DoWhileStatement', 38 | 'ExistentialTypeParam', 39 | 'ForInStatement', 40 | 'ForOfStatement', 41 | 'ForStatement', 42 | 'FunctionExpression', 43 | 'FunctionTypeAnnotation', 44 | 'FunctionTypeParam', 45 | 'InterfaceDeclaration', 46 | 'InterfaceExtends', 47 | 'IntersectionTypeAnnotation', 48 | 'MetaProperty', 49 | 'NewExpression', 50 | 'Noop', 51 | 'ObjectTypeCallProperty', 52 | 'ObjectTypeIndexer', 53 | 'ObjectTypeProperty', 54 | 'ParenthesizedExpression', 55 | 'QualifiedTypeIdentifier', 56 | 'RestElement', 57 | 'RestProperty', 58 | 'SequenceExpression', 59 | 'SpreadElement', 60 | 'SwitchCase', 61 | 'SwitchStatement', 62 | 'TaggedTemplateExpression', 63 | 'TemplateElement', 64 | 'TemplateLiteral', 65 | 'TryStatement', 66 | 'UnionTypeAnnotation', 67 | 'WhileStatement', 68 | 'WithStatement', 69 | 'YieldExpression', 70 | ]); 71 | 72 | const PRINTERS = getPrinters(); 73 | 74 | describe('missing-printers', () => { 75 | Object.keys(VISITOR_KEYS).forEach(key => { 76 | if (!UNIMPLEMENTED.has(key)) { 77 | it('has printer for node type: ' + key, () => { 78 | expect(PRINTERS[key]).toBeTruthy(); 79 | }); 80 | } else { 81 | it('does not have printer for unimplemented node type: ' + key, () => { 82 | expect(PRINTERS[key]).not.toBeTruthy(); 83 | }); 84 | } 85 | }); 86 | 87 | Object.keys(PRINTERS).forEach(key => { 88 | if (!EXTRA_PRINTERS.has(key)) { 89 | it('does not have printer for unknown node type: ' + key, () => { 90 | expect(VISITOR_KEYS[key]).toBeTruthy(); 91 | }); 92 | } else { 93 | it('has printer for "fake" node type: ' + key, () => { 94 | expect(VISITOR_KEYS[key]).not.toBeTruthy(); 95 | }); 96 | } 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /src/__tests__/tokens_spelling-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | jest.autoMockOff(); 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | const IGNORE = new Set([ 10 | 'scopeCloseNoDedent', 11 | 'scopeEmptyOrBreak', 12 | 'scopeEmptyOrCloseParen', 13 | 'scopeEmptyOrComma', 14 | 'scopeEmptyOrDedent', 15 | 'scopeEmptyOrIndent', 16 | 'scopeEmptyOrOpenParen', 17 | 'scopeOpenNoIndent', 18 | 'scopeSpaceOrBreak', 19 | ]); 20 | 21 | describe('tokens-spelling', () => { 22 | Object.keys(Tokens).forEach(key => { 23 | if (!IGNORE.has(key)) { 24 | it('Tokens.' + key + '() should have correct type', () => { 25 | expect(Tokens[key]().type).toBe(key); 26 | }); 27 | } 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/applyRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import assert from 'assert'; 8 | 9 | export default function applyRules(rules, originalTokens, context) { 10 | const finalTokens = rules.reduce( 11 | (tokens, rule) => rule({ 12 | ...context, 13 | tokens, 14 | }), 15 | originalTokens, 16 | ); 17 | 18 | // The final tokens must all be strings. 19 | finalTokens.forEach(token => { 20 | assert( 21 | token, 22 | 'A final token is null. After running all rules all tokens must ' + 23 | 'be string tokens.' 24 | ); 25 | assert( 26 | token.type === 'string', 27 | 'A final token has the type: "' + 28 | token.type + 29 | '". After running all rules all tokens must be string tokens.' 30 | ); 31 | }); 32 | 33 | // Concatenate them into the final result. 34 | return finalTokens.map(token => token.value).join(''); 35 | } 36 | -------------------------------------------------------------------------------- /src/fjs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import type {Input, Output} from './types'; 8 | 9 | import applyRules from './applyRules'; 10 | import * as babel from 'babel-core'; 11 | import getGlobalContext from './getGlobalContext'; 12 | import getMiddleware from './getMiddleware'; 13 | import getPrinters from './getPrinters'; 14 | import getRules from './getRules'; 15 | import print from './print'; 16 | 17 | export default function fjs(input: Input): Output { 18 | const {ast} = babel.transform(input.code, { 19 | plugins: [ 20 | 'syntax-flow', 21 | 'syntax-jsx', 22 | 'syntax-object-rest-spread', 23 | 'syntax-trailing-function-commas', 24 | 'babel-plugin-syntax-async-functions', 25 | ], 26 | }); 27 | const globalContext = getGlobalContext(ast); 28 | const tokens = print( 29 | getPrinters(), 30 | getMiddleware(), 31 | globalContext, 32 | ast, 33 | ); 34 | const code = applyRules(getRules(), tokens, globalContext); 35 | return {code}; 36 | } 37 | -------------------------------------------------------------------------------- /src/getGlobalContext.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | /** 8 | * This is context that is available everywhere that never changes. This is how 9 | * you can pass arbitrary information built on the first print call to all other 10 | * printers, middleware, etc. 11 | */ 12 | export default function getGlobalContext(node) { 13 | return { 14 | options: { 15 | maxLineLength: 80, 16 | }, 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /src/getMiddleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | import {flatMap} from './utils'; 10 | 11 | /** 12 | * Middleware is applied to all nodes after they have been printed. In addition 13 | * to everything in the printer context the middleware context will also contain 14 | * an array of the tokens that have already been printed. 15 | * 16 | * The application order of middleware is arbitrary, do not rely on a certain 17 | * order. 18 | */ 19 | export default function getMiddleware() { 20 | return { 21 | Comments: ({node, print, tokens}) => { 22 | if (node.leadingComments) { 23 | const leadingTokens = node.leadingComments.map((comment, i, arr) => { 24 | const parts = [print(comment)]; 25 | const next = i === arr.length - 1 ? node : arr[i + 1]; 26 | const min = comment.loc.end.line; 27 | const max = next.loc.start.line; 28 | for (let j = 0; j < max - min; j++) { 29 | parts.push(Tokens.string('\n')); 30 | } 31 | return parts; 32 | }); 33 | return [ 34 | ...leadingTokens, 35 | ...tokens, 36 | ]; 37 | } 38 | return tokens; 39 | }, 40 | }; 41 | }; 42 | -------------------------------------------------------------------------------- /src/getPrinters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | import classes from './printers/classes'; 10 | import comments from './printers/comments'; 11 | import expressions from './printers/expressions'; 12 | import flow from './printers/flow'; 13 | import functions from './printers/functions'; 14 | import importExport from './printers/importExport'; 15 | import jsx from './printers/jsx'; 16 | import literals from './printers/literals'; 17 | import misc from './printers/misc'; 18 | import object from './printers/object'; 19 | import obsolete from './printers/obsolete'; 20 | import patterns from './printers/patterns'; 21 | import statements from './printers/statements'; 22 | 23 | /** 24 | * Printers convert an AST into tokens which may then be formatted. 25 | */ 26 | export default function getPrinters() { 27 | return { 28 | ...classes, 29 | ...comments, 30 | ...expressions, 31 | ...flow, 32 | ...functions, 33 | ...importExport, 34 | ...jsx, 35 | ...literals, 36 | ...misc, 37 | ...object, 38 | ...obsolete, 39 | ...patterns, 40 | ...statements, 41 | }; 42 | }; 43 | -------------------------------------------------------------------------------- /src/getRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | import assert from 'assert'; 10 | import {endsWithNewLine, hasNonWhitespace} from './regex'; 11 | 12 | // Higher priority is better. 13 | const DEFAULT_PRIORITY = 1; 14 | const SCOPE_PRIORITY = new Map([ 15 | // Always break this if something needs to break. 16 | ['ternary', 4], 17 | ['logical_expressions', 2], 18 | ['binary_expressions', 2], 19 | ]); 20 | 21 | // This is the penalty to the number of breaks for certain kinds of scopes. 22 | // This prevents things like empty call expressions from having 2 free breaks. 23 | // A lower penalty means more likely to break. 24 | const DEFAULT_PENALTY = 0; 25 | const SCOPE_BREAK_PENALTY = new Map([ 26 | ['logical_expressions', 2], 27 | ['binary_expressions', 2], 28 | ]); 29 | 30 | /** 31 | * Rules convert an array of tokens into another array of tokens. Rules 32 | * are run in the particular order they are defined. Once all rules are 33 | * run all tokens must be string tokens. 34 | */ 35 | export default function getRules() { 36 | return [ 37 | ({tokens}) => tokens.filter(token => !!token), 38 | 39 | // First assign ids to all the scopes. 40 | ({tokens}) => { 41 | let id = 1; 42 | const stack = []; 43 | const push = () => { stack.push(id++); }; 44 | const pop = () => { stack.pop(); }; 45 | const peek = () => stack[stack.length - 1]; 46 | return tokens.map(token => { 47 | let scopeID = null; 48 | if (token.type === 'scopeOpen') { 49 | push(); 50 | scopeID = peek(); 51 | } else if (token.type === 'scopeClose') { 52 | scopeID = peek(); 53 | pop(); 54 | } else if (token.scope) { 55 | scopeID = peek(); 56 | } 57 | 58 | if (token.scope) { 59 | return { 60 | ...token, 61 | scopeID, 62 | }; 63 | } else { 64 | return token; 65 | } 66 | }); 67 | }, 68 | 69 | // Rudementary scope breaking. 70 | ({tokens, options}) => { 71 | // We will keep trying to break lines until they stop breaking. 72 | let someLinesBroke = true; 73 | while (someLinesBroke) { 74 | someLinesBroke = false; 75 | 76 | // First we need to recompute the lines. 77 | const lines = computeLines(tokens); 78 | 79 | // Compute the indentation of each line assuming there are no breaks. 80 | const indents = computeIndents(tokens, lines); 81 | 82 | // Figure out how many breaks are in each scope. 83 | const scopeBreaks = computeScopeBreaks(tokens); 84 | 85 | // Track the scopes to break. 86 | const scopesToBreak = new Set(); 87 | 88 | for (let i = 0; i < lines.length; i++) { 89 | const [start, end] = lines[i]; 90 | 91 | let alreadyHasBrokenScope = false; 92 | let spaceUsedByLine = indents[i] * 2; 93 | let scopeIndices = []; 94 | 95 | for (let j = start; j < end; j++) { 96 | if (tokens[j].scope) { 97 | scopeIndices.push(j); 98 | if (scopesToBreak.has(tokens[j].scopeID)) { 99 | alreadyHasBrokenScope = true; 100 | break; 101 | } 102 | } 103 | const token = tokens[j].scope ? tokens[j].unbroken : tokens[j]; 104 | const spaceUsedByToken = measure(token); 105 | if (spaceUsedByToken > 0) { 106 | spaceUsedByLine += spaceUsedByToken; 107 | } 108 | } 109 | 110 | // Don't need to break something manually, some other line has caused 111 | // a scope in thie line to break. We will check that scope first. 112 | if (alreadyHasBrokenScope) { 113 | continue; 114 | } 115 | 116 | // TODO: We can track the spacing between token groups based to 117 | // help choose which scope to break. E.g. Scope 1 results in groups 118 | // of size (5, 10, 7, 8) which is evenly distributed, but Scope 2 119 | // has groups of size (1, 30, 1) which means it's a bad scope. 120 | 121 | // Now we need to find a scope to break in this line. For now we 122 | // naively select the first scope we see. 123 | if ( 124 | spaceUsedByLine > options.maxLineLength && 125 | scopeIndices.length > 0 126 | ) { 127 | 128 | let maxIndex = 0; 129 | let _maxKind = tokens[scopeIndices[maxIndex]].kind; 130 | let _maxID = tokens[scopeIndices[maxIndex]].scopeID; 131 | let _maxPriority = SCOPE_PRIORITY.has(_maxKind) 132 | ? SCOPE_PRIORITY.get(_maxKind) 133 | : DEFAULT_PRIORITY; 134 | let _maxPenalty = SCOPE_BREAK_PENALTY.has(_maxKind) 135 | ? SCOPE_BREAK_PENALTY.get(_maxKind) 136 | : DEFAULT_PENALTY; 137 | let _maxBreaks = scopeBreaks.get(_maxID) - _maxPenalty; 138 | let maxValue = _maxPriority * _maxBreaks; 139 | 140 | for (let j = 1; j < scopeIndices.length; j++) { 141 | const currIndex = j; 142 | const currToken = tokens[scopeIndices[currIndex]]; 143 | const currID = currToken.scopeID; 144 | const currKind = currToken.kind; 145 | const currPriority = SCOPE_PRIORITY.has(currKind) 146 | ? SCOPE_PRIORITY.get(currKind) 147 | : DEFAULT_PRIORITY; 148 | const currPenalty = SCOPE_BREAK_PENALTY.has(currKind) 149 | ? SCOPE_BREAK_PENALTY.get(currKind) 150 | : DEFAULT_PENALTY; 151 | const currBreaks = scopeBreaks.get(currID) - currPenalty; 152 | const currValue = currPriority * currBreaks; 153 | 154 | if (currValue > maxValue) { 155 | maxIndex = currIndex; 156 | maxValue = currValue; 157 | } 158 | } 159 | 160 | scopesToBreak.add(tokens[scopeIndices[maxIndex]].scopeID); 161 | } 162 | } 163 | 164 | if (scopesToBreak.size > 0) { 165 | // Break the scopes. 166 | scopesToBreak.forEach(scopeID => { 167 | tokens = breakScopeID(tokens, scopeID); 168 | }); 169 | someLinesBroke = true; 170 | scopesToBreak.clear(); 171 | } 172 | } 173 | 174 | // TODO: Any call expressions (or other parenthesized things) that have 175 | // child scopes that break should also always break. 176 | 177 | return tokens; 178 | }, 179 | 180 | // We are done breaking scopes, now mark all remaining scopes as unbroken. 181 | ({tokens}) => tokens.map(token => token.scope ? token.unbroken : token), 182 | 183 | // Remove extra breaks. Simplified for now, we need to traverse other 184 | // non printable characters to remove extra breaks in the future. 185 | ({tokens}) => { 186 | let seenBreak = false; 187 | return tokens.filter(token => { 188 | if (token.type === 'break') { 189 | if (seenBreak) { 190 | return false; 191 | } else { 192 | seenBreak = true; 193 | return true; 194 | } 195 | } else if (measure(token) > 0) { 196 | seenBreak = false; 197 | } 198 | return true; 199 | }); 200 | }, 201 | 202 | // Map the final tokens back to strings and indentation. 203 | ({tokens}) => tokens.map(token => { 204 | switch (token.type) { 205 | case 'break': 206 | return Tokens.string('\n'); 207 | 208 | case 'colon': 209 | return Tokens.string(':'); 210 | 211 | case 'comma': 212 | return Tokens.string(','); 213 | 214 | case 'empty': 215 | return Tokens.string(''); 216 | 217 | case 'period': 218 | return Tokens.string('.'); 219 | 220 | case 'semiColon': 221 | return Tokens.string(';'); 222 | 223 | case 'space': 224 | return Tokens.string(' '); 225 | 226 | case 'questionMark': 227 | return Tokens.string('?'); 228 | 229 | case 'indent': 230 | case 'dedent': 231 | case 'string': 232 | return token; 233 | 234 | default: 235 | assert(false, 'Unhandled token type while printing: ' + token.type); 236 | return null; 237 | } 238 | }), 239 | 240 | // Handle indentation. Now everything should be strings. 241 | ({tokens}) => { 242 | let indent = 0; 243 | let canIndent = false; 244 | return tokens.map(token => { 245 | if (token.type === 'indent') { 246 | indent++; 247 | return null; 248 | } 249 | 250 | if (token.type === 'dedent') { 251 | indent--; 252 | return null; 253 | } 254 | 255 | if (token.type === 'string') { 256 | const value = token.value; 257 | let result = token; 258 | // If we canIndent, and there is some non-whitespace character in 259 | // this token, indent then set canIndent to false. 260 | if (canIndent && indent > 0 && hasNonWhitespace(value)) { 261 | result = Tokens.string(' '.repeat(indent) + value); 262 | canIndent = false; 263 | } 264 | if (endsWithNewLine(value)) { 265 | canIndent = true; 266 | } 267 | return result; 268 | } 269 | 270 | assert(false, 'Unhandled token type while indenting: ' + token.type); 271 | return null; 272 | }); 273 | }, 274 | 275 | ({tokens}) => tokens.filter(token => !!token), 276 | ]; 277 | }; 278 | 279 | ////////// Some private helpers used for scope breaking. ////////// 280 | 281 | function endOfLine(token) { 282 | if (token.scope) { 283 | return endOfLine(token.unbroken); 284 | } 285 | 286 | switch (token.type) { 287 | case 'string': 288 | return endsWithNewLine(token.value); 289 | 290 | case 'break': 291 | return true; 292 | 293 | default: 294 | return false; 295 | } 296 | } 297 | 298 | function measure(token) { 299 | // Measure the unbroken side of a scope token. 300 | if (token.scope) { 301 | return measure(token.unbroken); 302 | } 303 | 304 | switch (token.type) { 305 | case 'string': 306 | return token.value.length; 307 | 308 | case 'colon': 309 | case 'comma': 310 | case 'period': 311 | case 'semiColon': 312 | case 'space': 313 | case 'questionMark': 314 | return 1; 315 | 316 | default: 317 | return 0; 318 | } 319 | } 320 | 321 | function breakScopeID(tokens, scopeID) { 322 | return tokens.map(token => 323 | token.scopeID === scopeID 324 | ? token.broken 325 | : token 326 | ); 327 | } 328 | 329 | /** 330 | * This will compute the lines based on token indices in the given array. 331 | * 332 | * Each line is: [token index inclusive, token index exclusive) 333 | */ 334 | function computeLines(tokens) { 335 | let lines = []; 336 | for (let i = 0; i < tokens.length; i++) { 337 | if (endOfLine(tokens[i]) || (i === tokens.length - 1)) { 338 | if (lines.length === 0) { 339 | lines.push([0, i + 1]); 340 | } else { 341 | lines.push([lines[lines.length - 1][1], i + 1]); 342 | } 343 | } 344 | } 345 | return lines; 346 | } 347 | 348 | /** 349 | * This computes the indentation of each line assuming no scopes break. 350 | */ 351 | function computeIndents(tokens, lines) { 352 | let indent = 0; 353 | return lines.map(line => { 354 | // Only capture the indent once we see a printable character. 355 | let capturedIndent = -1; 356 | for (let i = line[0]; i < line[1]; i++) { 357 | const token = tokens[i].scope ? tokens[i].unbroken : tokens[i]; 358 | if (token.type === 'indent') { 359 | indent++; 360 | } else if (token.type === 'dedent') { 361 | indent--; 362 | } 363 | 364 | if (measure(token) > 0 && capturedIndent < 0) { 365 | capturedIndent = indent; 366 | } 367 | } 368 | return capturedIndent < 0 ? indent : capturedIndent; 369 | }); 370 | } 371 | 372 | /** 373 | * Counts the number of breaks that would result from a scope breaking. 374 | */ 375 | function computeScopeBreaks(tokens) { 376 | const scopeBreaks = new Map(); 377 | for (const token of tokens) { 378 | if (token.scope) { 379 | if (!scopeBreaks.has(token.scopeID)) { 380 | scopeBreaks.set(token.scopeID, 0); 381 | } 382 | if (token.broken.type === 'break') { 383 | scopeBreaks.set(token.scopeID, scopeBreaks.get(token.scopeID) + 1); 384 | } 385 | } 386 | } 387 | return scopeBreaks; 388 | } 389 | -------------------------------------------------------------------------------- /src/print.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import assert from 'assert'; 8 | import {flatten} from './utils'; 9 | 10 | export default function print(printers, middleware, globalContext, node) { 11 | const path = [node]; 12 | const applyMiddleware = getApplyMiddlewareFn(middleware); 13 | const printFn = getPrintFn(printers, applyMiddleware, path); 14 | return flatten(printFn(node)); 15 | } 16 | 17 | function getPrintFn(printers, applyMiddleware, globalContext, originalPath) { 18 | return function printFn(node) { 19 | if (!node) { 20 | return []; 21 | } 22 | const type = node.type; 23 | if (!type) { 24 | return []; 25 | } 26 | const printer = printers[type]; 27 | if (!printer) { 28 | assert(false, 'Unrecognized type: ' + type); 29 | return []; 30 | } 31 | const nextPath = [].concat(originalPath, node); 32 | const printerContext = { 33 | ...globalContext, 34 | path: nextPath, 35 | print: getPrintFn(printers, applyMiddleware, globalContext, nextPath), 36 | node, 37 | }; 38 | const tokens = flatten(printer(printerContext)); 39 | const result = applyMiddleware(printerContext, tokens); 40 | return flatten(result); 41 | }; 42 | } 43 | 44 | function getApplyMiddlewareFn(middleware) { 45 | const middlewareArray = Object.keys(middleware).map(key => middleware[key]); 46 | return function applyMiddleware(printerContext, originalTokens) { 47 | const result = middlewareArray.reduce( 48 | (tokens, middlewareToApply) => flatten(middlewareToApply({ 49 | ...printerContext, 50 | tokens, 51 | })), 52 | originalTokens, 53 | ); 54 | return result; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/printers/classes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | import {printList, printStatements} from '../utils'; 10 | 11 | export default { 12 | ClassBody: ({node, print}) => [ 13 | // TODO: Inner comments. 14 | Tokens.string('{'), 15 | Tokens.break(), 16 | Tokens.indent(), 17 | printStatements(node.body, print), 18 | Tokens.break(), 19 | Tokens.dedent(), 20 | Tokens.string('}'), 21 | ], 22 | 23 | ClassDeclaration: ({node, print}) => [ 24 | Tokens.string('class'), 25 | Tokens.space(), 26 | print(node.id), 27 | print(node.typeParameters), 28 | Tokens.space(), 29 | node.superClass && [ 30 | Tokens.string('extends'), 31 | Tokens.space(), 32 | print(node.superClass), 33 | print(node.superTypeParameters), 34 | Tokens.space(), 35 | ], 36 | print(node.body), 37 | Tokens.break(), 38 | ], 39 | 40 | ClassMethod: ({node, print}) => [ 41 | node.static && [ 42 | Tokens.string('static'), 43 | Tokens.space(), 44 | ], 45 | node.async && [ 46 | Tokens.string('async'), 47 | Tokens.space(), 48 | ], 49 | print(node.key), 50 | Tokens.string('('), 51 | printList(node.params, print), 52 | Tokens.string(')'), 53 | print(node.returnType), 54 | Tokens.space(), 55 | print(node.body), 56 | Tokens.break(), 57 | ], 58 | 59 | ClassProperty: ({node, print}) => [ 60 | node.static && [ 61 | Tokens.string('static'), 62 | Tokens.space(), 63 | ], 64 | print(node.key), 65 | print(node.typeAnnotation), 66 | node.value && [ 67 | Tokens.space(), 68 | Tokens.string('='), 69 | Tokens.space(), 70 | print(node.value), 71 | ], 72 | Tokens.semiColon(), 73 | Tokens.break(), 74 | ], 75 | }; 76 | -------------------------------------------------------------------------------- /src/printers/comments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | export default { 10 | CommentLine: ({node}) => [ 11 | Tokens.string('//'), 12 | Tokens.string(node.value), 13 | ], 14 | 15 | CommentBlock: ({node}) => [ 16 | Tokens.string('/*'), 17 | Tokens.string(node.value), 18 | Tokens.string('*/'), 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /src/printers/expressions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | import Tokens from '../Tokens'; 9 | 10 | import {map, printList} from '../utils'; 11 | 12 | export default { 13 | ArrayExpression: ({node, print}) => Printers.Array({ 14 | elements: node.elements, 15 | print, 16 | }), 17 | 18 | // ArrowFunctionExpression: ({node, print}) => [], 19 | 20 | AssignmentExpression: ({node, print}) => Printers.Assignment({ 21 | left: node.left, 22 | right: node.right, 23 | print, 24 | }), 25 | 26 | AwaitExpression: ({node, print}) => [ 27 | Tokens.string('await'), 28 | Tokens.space(), 29 | print(node.argument), 30 | ], 31 | 32 | BinaryExpression: ({node, path, print}) => { 33 | const parenthesized = node.extra && node.extra.parenthesized; 34 | 35 | let hasParentBinaryExpression = false; 36 | 37 | // Note: We don't check the last node, it's always a LogicalExpression since 38 | // that's the node we are printing. 39 | for (let i = 0; i < path.length - 1; i++) { 40 | if (path[i] && path[i].type === 'BinaryExpression') { 41 | hasParentBinaryExpression = true; 42 | break; 43 | } 44 | } 45 | 46 | const createScope = !hasParentBinaryExpression && !parenthesized; 47 | 48 | return [ 49 | parenthesized && Tokens.string('('), 50 | parenthesized && Tokens.scopeOpen('binary_expressions'), 51 | createScope && Tokens.scopeOpenNoIndent('binary_expressions'), 52 | 53 | Tokens.scopeEmptyOrBreak(), 54 | print(node.left), 55 | Tokens.space(), 56 | Tokens.string(node.operator), 57 | Tokens.scopeSpaceOrBreak(), 58 | print(node.right), 59 | 60 | createScope && Tokens.scopeCloseNoDedent(), 61 | parenthesized && Tokens.scopeEmptyOrBreak(), 62 | parenthesized && Tokens.scopeClose(), 63 | parenthesized && Tokens.string(')'), 64 | ]; 65 | }, 66 | 67 | BindExpression: ({node, print}) => [ 68 | print(node.object), 69 | Tokens.colon(), 70 | Tokens.colon(), 71 | print(node.callee), 72 | ], 73 | 74 | CallExpression: ({node, print}) => [ 75 | print(node.callee), 76 | Tokens.string('('), 77 | printList(node.arguments, print, 'call_expression'), 78 | Tokens.string(')'), 79 | ], 80 | 81 | // ClassExpression: ({node, print}) => [], 82 | 83 | ConditionalExpression: ({node, print}) => [ 84 | print(node.test), 85 | Tokens.scopeOpen('ternary'), 86 | Tokens.scopeSpaceOrBreak(), 87 | Tokens.questionMark(), 88 | Tokens.space(), 89 | print(node.consequent), 90 | Tokens.scopeSpaceOrBreak(), 91 | Tokens.colon(), 92 | Tokens.space(), 93 | print(node.alternate), 94 | Tokens.scopeClose(), 95 | ], 96 | 97 | // DoExpression: ({node, print}) => [], 98 | // FunctionExpression: ({node, print}) => [], 99 | 100 | Identifier: ({node, print}) => [ 101 | Tokens.string(node.name), 102 | print(node.typeAnnotation), 103 | ], 104 | 105 | LogicalExpression: ({node, path, print}) => { 106 | const parenthesized = node.extra && node.extra.parenthesized; 107 | 108 | let hasParentLogicalExpression = false; 109 | 110 | // Note: We don't check the last node, it's always a LogicalExpression since 111 | // that's the node we are printing. 112 | for (let i = 0; i < path.length - 1; i++) { 113 | if (path[i] && path[i].type === 'LogicalExpression') { 114 | hasParentLogicalExpression = true; 115 | break; 116 | } 117 | } 118 | 119 | const createScope = !hasParentLogicalExpression && !parenthesized; 120 | 121 | // TODO: This part is basically untested... make some logical chains inside 122 | // of ifs and function calls, etc. 123 | 124 | // This determines if while breaking the scope we need to add parens or not. 125 | // For example a naked series of logical expressions will need parenthesis 126 | // added to them. 127 | const createScopeParens = createScope && !path.some(pn => pn && ( 128 | ( 129 | pn.type === 'CallExpression' && 130 | pn.arguments.some(argument => argument === node) 131 | ) || 132 | ( 133 | pn.type === 'IfStatement' && 134 | pn.test === node 135 | ) 136 | )); 137 | 138 | return [ 139 | parenthesized && Tokens.string('('), 140 | parenthesized && Tokens.scopeOpen('logical_expressions'), 141 | createScope && Tokens.scopeOpenNoIndent('logical_expressions'), 142 | createScopeParens && Tokens.scopeEmptyOrOpenParen(), 143 | createScope && Tokens.scopeEmptyOrIndent(), 144 | 145 | Tokens.scopeEmptyOrBreak(), 146 | print(node.left), 147 | Tokens.space(), 148 | Tokens.string(node.operator), 149 | Tokens.scopeSpaceOrBreak(), 150 | print(node.right), 151 | 152 | createScope && Tokens.scopeEmptyOrBreak(), 153 | createScope && Tokens.scopeEmptyOrDedent(), 154 | createScopeParens && Tokens.scopeEmptyOrCloseParen(), 155 | createScope && Tokens.scopeCloseNoDedent(), 156 | parenthesized && Tokens.scopeEmptyOrBreak(), 157 | parenthesized && Tokens.scopeClose(), 158 | parenthesized && Tokens.string(')'), 159 | ]; 160 | }, 161 | 162 | MemberExpression: ({node, print}) => [ 163 | print(node.object), 164 | node.computed && Tokens.string('['), 165 | (!node.computed) && Tokens.period(), 166 | print(node.property), 167 | node.computed && Tokens.string(']'), 168 | ], 169 | 170 | // NewExpression: ({node, print}) => [], 171 | 172 | ObjectExpression: ({node, print}) => Printers.Object({ 173 | properties: node.properties, 174 | print, 175 | }), 176 | 177 | // ParenthesizedExpression: ({node, print}) => [], 178 | // SequenceExpression: ({node, print}) => [], 179 | 180 | Super: () => Tokens.string('super'), 181 | 182 | // TaggedTemplateExpression: ({node, print}) => [], 183 | 184 | ThisExpression: () => Tokens.string('this'), 185 | 186 | UnaryExpression: ({node, print}) => [ 187 | node.prefix && Tokens.string(node.operator), 188 | node.extra.parenthesizedArgument && Tokens.string('('), 189 | print(node.argument), 190 | node.extra.parenthesizedArgument && Tokens.string(')'), 191 | (!node.prefix) && Tokens.string(node.operator), 192 | ], 193 | 194 | UpdateExpression: ({node, print}) => [ 195 | node.prefix && Tokens.string(node.operator), 196 | print(node.argument), 197 | (!node.prefix) && Tokens.string(node.operator), 198 | ], 199 | 200 | // YieldExpression: ({node, print}) => [], 201 | }; 202 | -------------------------------------------------------------------------------- /src/printers/flow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | import Tokens from '../Tokens'; 9 | 10 | import assert from 'assert'; 11 | import {printList} from '../utils'; 12 | 13 | export default { 14 | AnyTypeAnnotation: () => Tokens.string('any'), 15 | 16 | BooleanTypeAnnotation: () => Tokens.string('boolean'), 17 | 18 | BooleanLiteralTypeAnnotation: ({node}) => node.value 19 | ? Tokens.string('true') 20 | : Tokens.string('false'), 21 | 22 | GenericTypeAnnotation: ({node, print}) => [ 23 | print(node.id), 24 | print(node.typeParameters), 25 | ], 26 | 27 | MixedTypeAnnotation: () => Tokens.string('mixed'), 28 | 29 | NullableTypeAnnotation: ({node, print}) => [ 30 | Tokens.questionMark(), 31 | print(node.typeAnnotation), 32 | ], 33 | 34 | NullLiteralTypeAnnotation: () => Token.string('null'), 35 | 36 | NumberTypeAnnotation: () => Tokens.string('number'), 37 | 38 | NumericLiteralTypeAnnotation: ({node}) => Tokens.string(node.extra.raw), 39 | 40 | StringLiteralTypeAnnotation: ({node}) => Printers.String({ 41 | value: node.value, 42 | quotes: 'single', 43 | }), 44 | 45 | StringTypeAnnotation: () => Tokens.string('string'), 46 | 47 | ThisTypeAnnotation: () => Tokens.string('this'), 48 | 49 | TupleTypeAnnotation: ({node, print}) => [ 50 | Tokens.string('['), 51 | printList(node.types, print), 52 | Tokens.string(']'), 53 | ], 54 | 55 | TypeAlias: ({node, print}) => [ 56 | Tokens.string('type'), 57 | Tokens.space(), 58 | print(node.id), 59 | print(node.typeParameters), 60 | Tokens.space(), 61 | Tokens.string('='), 62 | Tokens.space(), 63 | print(node.right), 64 | Tokens.semiColon(), 65 | Tokens.break(), 66 | ], 67 | 68 | TypeAnnotation: ({node, print}) => [ 69 | Tokens.string(':'), 70 | Tokens.space(), 71 | print(node.typeAnnotation), 72 | ], 73 | 74 | TypeCastExpression: ({node, print}) => [ 75 | Tokens.string('('), 76 | print(node.expression), 77 | print(node.typeAnnotation), 78 | Tokens.string(')'), 79 | ], 80 | 81 | TypeofTypeAnnotation: ({node, print}) => [ 82 | Tokens.string('typeof'), 83 | Tokens.space(), 84 | print(node.argument), 85 | ], 86 | 87 | TypeParameter: ({node, print}) => [ 88 | node.variance === 'plus' && Tokens.string('+'), 89 | node.variance === 'minus' && Tokens.string('-'), 90 | Tokens.string(node.name), 91 | print(node.bound), 92 | ], 93 | 94 | TypeParameterDeclaration: ({node, print}) => [ 95 | Tokens.string('<'), 96 | printList(node.params, print), 97 | Tokens.string('>'), 98 | ], 99 | 100 | TypeParameterInstantiation: ({node, print}) => [ 101 | Tokens.string('<'), 102 | printList(node.params, print), 103 | Tokens.string('>'), 104 | ], 105 | 106 | VoidTypeAnnotation: () => Tokens.string('void'), 107 | }; 108 | -------------------------------------------------------------------------------- /src/printers/functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | import Tokens from '../Tokens'; 9 | 10 | export default { 11 | FunctionDeclaration: ({node, print}) => [ 12 | Printers.Function({ 13 | async: !!node.async, 14 | body: node.body, 15 | generator: !!node.generator, 16 | id: node.id, 17 | params: node.params, 18 | print, 19 | }), 20 | Tokens.break(), 21 | Tokens.string('\n'), 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /src/printers/importExport.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | import {map} from '../utils'; 10 | 11 | export default { 12 | ExportAllDeclaration: ({node, print}) => [], 13 | 14 | ExportDefaultDeclaration: ({node, print}) => [ 15 | Tokens.string('export'), 16 | Tokens.space(), 17 | Tokens.string('default'), 18 | Tokens.space(), 19 | print(node.declaration), 20 | ], 21 | 22 | ExportDefaultSpecifier: ({node, print}) => [], 23 | ExportNamedDeclaration: ({node, print}) => [], 24 | ExportNamespaceSpecifier: ({node, print}) => [], 25 | ExportSpecifier: ({node, print}) => [], 26 | 27 | ImportDeclaration: ({node, print}) => [ 28 | Tokens.string('import'), 29 | Tokens.space(), 30 | map(node.specifiers, (specifier, i) => [ 31 | i > 0 && [Tokens.comma(), Tokens.space()], 32 | print(specifier), 33 | ]), 34 | Tokens.space(), 35 | Tokens.string('from'), 36 | Tokens.space(), 37 | print(node.source), 38 | Tokens.semiColon(), 39 | Tokens.break(), 40 | ], 41 | 42 | ImportDefaultSpecifier: ({node, print}) => print(node.local), 43 | 44 | ImportNamespaceSpecifier: ({node, print}) => [], 45 | ImportSpecifier: ({node, print}) => [], 46 | }; 47 | -------------------------------------------------------------------------------- /src/printers/jsx.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | import Tokens from '../Tokens'; 9 | 10 | export default { 11 | JSXAttribute: ({node, print}) => [ 12 | print(node.name), 13 | Tokens.string('='), 14 | node.value && [ 15 | node.value.type === 'StringLiteral' && Printers.String({ 16 | value: node.value.value, 17 | quotes: 'double', 18 | }), 19 | node.value.type !== 'StringLiteral' && print(node.value), 20 | ], 21 | ], 22 | 23 | JSXClosingElement: ({node, print}) => [ 24 | Tokens.string(''), 27 | ], 28 | 29 | JSXElement: ({node, print}) => [ 30 | print(node.openingElement), 31 | node.children.length > 0 && [ 32 | Tokens.scopeOpen('jsx_children'), 33 | node.children.map(child => { 34 | const childTokens = print(child); 35 | return [ 36 | // Only insert the break if the child is printable. This is necessary 37 | // because there are "empty" JSXText nodes between every child. 38 | childTokens && Tokens.scopeEmptyOrBreak(), 39 | childTokens, 40 | ]; 41 | }), 42 | Tokens.scopeEmptyOrBreak(), 43 | Tokens.scopeClose(), 44 | ], 45 | print(node.closingElement), 46 | ], 47 | 48 | JSXEmptyExpression: () => [], 49 | 50 | JSXExpressionContainer: ({node, print}) => [ 51 | Tokens.string('{'), 52 | Tokens.scopeOpen('jsx_expression_container'), 53 | Tokens.scopeEmptyOrBreak(), 54 | print(node.expression), 55 | Tokens.scopeEmptyOrBreak(), 56 | Tokens.scopeClose(), 57 | Tokens.string('}'), 58 | ], 59 | 60 | JSXIdentifier: ({node}) => Tokens.string(node.name), 61 | 62 | JSXMemberExpression: ({node, print}) => [ 63 | print(node.object), 64 | Tokens.period(), 65 | print(node.property), 66 | ], 67 | 68 | JSXNamespacedName: ({node, print}) => [ 69 | print(node.namespace), 70 | Tokens.colon(), 71 | print(node.name), 72 | ], 73 | 74 | JSXOpeningElement: ({node, print}) => [ 75 | Tokens.string('<'), 76 | print(node.name), 77 | node.attributes.length && [ 78 | Tokens.scopeOpen('jsx_attributes'), 79 | node.attributes.map(attribute => [ 80 | Tokens.scopeSpaceOrBreak(), 81 | print(attribute), 82 | ]), 83 | node.selfClosing && Tokens.scopeSpaceOrBreak(), 84 | Tokens.scopeClose(), 85 | ], 86 | (!node.attributes.length) && node.selfClosing && Tokens.space(), 87 | node.selfClosing && Tokens.string('/'), 88 | Tokens.string('>'), 89 | ], 90 | 91 | JSXSpreadAttribute: ({node, print}) => [ 92 | Tokens.string('{'), 93 | Tokens.string('...'), 94 | print(node.argument), 95 | Tokens.string('}'), 96 | ], 97 | 98 | JSXText: ({node}) => node.value.trim() 99 | ? Tokens.string(node.value.trim()) 100 | : null, 101 | }; 102 | -------------------------------------------------------------------------------- /src/printers/literals.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | import Tokens from '../Tokens'; 9 | 10 | export default { 11 | BooleanLiteral: ({node}) => ( 12 | node.value ? Tokens.string('true') : Tokens.string('false') 13 | ), 14 | 15 | DirectiveLiteral: ({node}) => Printers.String({ 16 | value: node.value, 17 | quotes: 'single', 18 | }), 19 | 20 | NullLiteral: () => Tokens.string('null'), 21 | 22 | NumericLiteral: ({node}) => Tokens.string(node.extra.raw), 23 | 24 | RegExpLiteral: ({node}) => [ 25 | Tokens.string('/'), 26 | Tokens.string(node.pattern), 27 | Tokens.string('/'), 28 | node.flags && Tokens.string(node.flags), 29 | ], 30 | 31 | StringLiteral: ({node}) => Printers.String({ 32 | value: node.value, 33 | quotes: 'single', 34 | }), 35 | 36 | // TemplateLiteral: ({node, print}) => [], 37 | }; 38 | -------------------------------------------------------------------------------- /src/printers/misc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | import {printStatements} from '../utils'; 10 | 11 | export default { 12 | File: ({print, node}) => [ 13 | print(node.program), 14 | // Files end with new lines. Strip the wrapping File node if you 15 | // need to format a subset of the AST that should not be treated as 16 | // an entire file. 17 | Tokens.break(), 18 | ], 19 | 20 | Program: ({print, node}) => [ 21 | node.directives.length && [ 22 | printStatements(node.directives, print), 23 | Tokens.string('\n'), 24 | ], 25 | printStatements(node.body, print), 26 | ], 27 | 28 | // Uncategorized / WIP 29 | 30 | VariableDeclarator: ({print, node}) => [ 31 | print(node.id), 32 | node.init && [ 33 | Tokens.space(), 34 | Tokens.string('='), 35 | Tokens.space(), 36 | print(node.init), 37 | ], 38 | ], 39 | 40 | SpreadProperty: ({node, print}) => [ 41 | Tokens.string('...'), 42 | print(node.argument), 43 | ], 44 | 45 | Directive: ({node, print}) => [ 46 | print(node.value), 47 | Tokens.semiColon(), 48 | Tokens.break(), 49 | ], 50 | }; 51 | -------------------------------------------------------------------------------- /src/printers/object.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | import {printList} from '../utils'; 10 | 11 | export default { 12 | ObjectProperty: ({print, node}) => [ 13 | node.computed 14 | ? [ 15 | Tokens.string('['), 16 | print(node.key), 17 | Tokens.string(']') 18 | ] 19 | : print(node.key), 20 | node.value.type === 'AssignmentPattern' 21 | ? [ 22 | Tokens.space(), 23 | Tokens.string('='), 24 | Tokens.space(), 25 | print(node.value.right), 26 | ] 27 | : !node.shorthand && [ 28 | Tokens.colon(), 29 | Tokens.space(), 30 | print(node.value), 31 | ], 32 | ], 33 | 34 | ObjectMethod: ({print, node}) => [ 35 | node.kind === 'get' && [ 36 | Tokens.string('get'), 37 | Tokens.space(), 38 | ], 39 | node.kind === 'set' && [ 40 | Tokens.string('set'), 41 | Tokens.space(), 42 | ], 43 | node.async && [ 44 | Tokens.string('async'), 45 | Tokens.space(), 46 | ], 47 | node.generator && Tokens.string('*'), 48 | node.computed 49 | ? [ 50 | Tokens.string('['), 51 | print(node.key), 52 | Tokens.string(']') 53 | ] 54 | : print(node.key), 55 | Tokens.string('('), 56 | printList(node.params, print), 57 | Tokens.string(')'), 58 | print(node.returnType), 59 | Tokens.space(), 60 | print(node.body), 61 | ], 62 | }; 63 | -------------------------------------------------------------------------------- /src/printers/obsolete.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import assert from 'assert'; 8 | 9 | export default { 10 | ArrayTypeAnnotation: () => assert(false, 'Obsolete node type.'), 11 | ObjectTypeAnnotation: () => assert(false, 'Obsolete node type.'), 12 | }; 13 | -------------------------------------------------------------------------------- /src/printers/patterns.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Printers from '../Printers'; 8 | 9 | export default { 10 | // let [a, b] = c; 11 | ArrayPattern: ({node, print}) => Printers.Array({ 12 | elements: node.elements, 13 | print, 14 | }), 15 | 16 | // function foo(a = 1) {} 17 | AssignmentPattern: ({node, print}) => Printers.Assignment({ 18 | left: node.left, 19 | right: node.right, 20 | print, 21 | }), 22 | 23 | // let {a, b: c} = d; 24 | ObjectPattern: ({node, print}) => Printers.Object({ 25 | properties: node.properties, 26 | print, 27 | }), 28 | }; 29 | -------------------------------------------------------------------------------- /src/printers/statements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from '../Tokens'; 8 | 9 | import {map, printList, printStatements} from '../utils'; 10 | 11 | export default { 12 | BlockStatement: ({node, print}) => [ 13 | // TODO: Inner comments. 14 | // TODO: Directives? 15 | Tokens.string('{'), 16 | node.body.length && [ 17 | Tokens.break(), 18 | Tokens.indent(), 19 | printStatements(node.body, print), 20 | Tokens.break(), 21 | Tokens.dedent(), 22 | ], 23 | Tokens.string('}'), 24 | ], 25 | 26 | BreakStatement: ({node, print}) => [ 27 | Tokens.string('break'), 28 | node.label && [ 29 | Tokens.space(), 30 | print(node.label), 31 | ], 32 | Tokens.semiColon(), 33 | Tokens.break(), 34 | ], 35 | 36 | ContinueStatement: ({node, print}) => [ 37 | Tokens.string('continue'), 38 | node.label && [ 39 | Tokens.space(), 40 | print(node.label), 41 | ], 42 | Tokens.semiColon(), 43 | Tokens.break(), 44 | ], 45 | 46 | DebuggerStatement: ({node, print}) => [ 47 | Tokens.string('debugger'), 48 | Tokens.semiColon(), 49 | Tokens.break(), 50 | ], 51 | 52 | // DeclareClass: ({node, print}) => [], 53 | // DeclareFunction: ({node, print}) => [], 54 | // DeclareInterface: ({node, print}) => [], 55 | // DeclareModule: ({node, print}) => [], 56 | // DeclareTypeAlias: ({node, print}) => [], 57 | // DeclareVariable: ({node, print}) => [], 58 | // DoWhileStatement: ({node, print}) => [], 59 | 60 | EmptyStatement: ({node, print}) => Tokens.semiColon(), 61 | 62 | ExpressionStatement: ({print, node}) => [ 63 | print(node.expression), 64 | Tokens.semiColon(), 65 | Tokens.break(), 66 | ], 67 | 68 | // ForInStatement: ({node, print}) => [], 69 | // ForOfStatement: ({node, print}) => [], 70 | // ForStatement: ({node, print}) => [], 71 | 72 | FunctionDeclaration: ({node, print}) => [ 73 | Tokens.string('function'), 74 | Tokens.space(), 75 | print(node.id), 76 | Tokens.string('('), 77 | printList(node.params, print), 78 | Tokens.string(')'), 79 | Tokens.space(), 80 | print(node.body), 81 | ], 82 | 83 | IfStatement: ({node, print}) => [ 84 | Tokens.string('if'), 85 | Tokens.space(), 86 | Tokens.string('('), 87 | print(node.test), 88 | Tokens.string(')'), 89 | Tokens.space(), 90 | print(node.consequent), 91 | (!node.alternate) && Tokens.break(), 92 | node.alternate && [ 93 | Tokens.space(), 94 | Tokens.string('else'), 95 | Tokens.space(), 96 | print(node.alternate), 97 | ], 98 | ], 99 | 100 | // InterfaceDeclaration: ({node, print}) => [], 101 | 102 | LabeledStatement: ({node, print}) => [ 103 | print(node.label), 104 | Tokens.colon(), 105 | Tokens.space(), 106 | print(node.body), 107 | ], 108 | 109 | ReturnStatement: ({node, print}) => [ 110 | Tokens.string('return'), 111 | node.argument != null && [ 112 | Tokens.space(), 113 | print(node.argument), 114 | ], 115 | Tokens.semiColon(), 116 | Tokens.break(), 117 | ], 118 | 119 | // SwitchStatement: ({node, print}) => [], 120 | 121 | ThrowStatement: ({node, print}) => [ 122 | Tokens.string('throw'), 123 | Tokens.space(), 124 | print(node.argument), 125 | Tokens.semiColon(), 126 | Tokens.break(), 127 | ], 128 | 129 | // TryStatement: ({node, print}) => [], 130 | 131 | VariableDeclaration: ({print, node}) => [ 132 | Tokens.string(node.kind), 133 | Tokens.space(), 134 | // Not quite the same as print list since there is no trailing comma. 135 | map(node.declarations, (declaration, i) => [ 136 | i > 0 && [Tokens.comma(), Tokens.space()], 137 | print(declaration), 138 | ]), 139 | Tokens.semiColon(), 140 | Tokens.break(), 141 | ], 142 | 143 | // WhileStatement: ({node, print}) => [], 144 | // WithStatement: ({node, print}) => [], 145 | }; 146 | -------------------------------------------------------------------------------- /src/regex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | export function endsWithNewLine(value) { 8 | return /^.*\n$/.test(value); 9 | } 10 | 11 | export function hasNonWhitespace(value) { 12 | return /^.*\S$/.test(value); 13 | } 14 | -------------------------------------------------------------------------------- /src/testFixtures.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import assert from 'assert'; 8 | import fjs from './fjs/'; 9 | import fs from 'fs'; 10 | import path from 'path'; 11 | 12 | /** 13 | * This will run tests for a particular directory in the fixtures folder. It is 14 | * used to split up the snapshot files into meaningful categories so that it is 15 | * not one giant output file. 16 | */ 17 | export default function testFixtures(dir, blacklist) { 18 | const fixturesPath = path.join(__dirname, '__fixtures__', dir); 19 | buildFixtures(fixturesPath).forEach(fixture => { 20 | if (!blacklist || !blacklist.has(fixture.name)) { 21 | it(fixture.name, () => { 22 | const inputCode = fixture.input; 23 | const input = {code: inputCode}; 24 | const output = fjs(input); 25 | const outputCode = output.code; 26 | expect(outputCode).toMatchSnapshot(); 27 | }); 28 | } 29 | }); 30 | } 31 | 32 | function buildFixtures(originalFilePath) { 33 | let arr = []; 34 | const filePaths = fs.readdirSync(originalFilePath); 35 | filePaths.forEach(fileName => { 36 | const filePath = path.join(originalFilePath, fileName); 37 | const stats = fs.statSync(filePath); 38 | if (stats.isDirectory()) { 39 | arr = [].concat(arr, buildFixtures(filePath)); 40 | } else if (stats.isFile()) { 41 | arr.push({ 42 | name: fileName, 43 | input: fs.readFileSync(filePath, 'utf8'), 44 | }); 45 | } 46 | }); 47 | return arr; 48 | } 49 | -------------------------------------------------------------------------------- /src/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | export type Input = { 8 | code: string, 9 | }; 10 | 11 | export type Output = { 12 | code: string, 13 | sourceMap: any, 14 | }; 15 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2004-present Facebook. All Rights Reserved. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | import Tokens from './Tokens'; 8 | 9 | /** 10 | * Maps over the given array, checks for null first. 11 | */ 12 | export function map(arr, fn) { 13 | return arr && arr.map(fn); 14 | } 15 | 16 | /** 17 | * Flattens an array recursively until it contains no more arrays. 18 | */ 19 | export function flatten(arr) { 20 | if (!Array.isArray(arr)) { 21 | return [arr]; 22 | } 23 | while (arr.some(el => Array.isArray(el))) { 24 | arr = Array.prototype.concat.apply([], arr); 25 | } 26 | return arr; 27 | } 28 | 29 | /** 30 | * Prints a comma separated list that is wrapped in a scope. 31 | */ 32 | export function printList(items, print, kind) { 33 | if (!items) { 34 | return null; 35 | } 36 | return [ 37 | Tokens.scopeOpen(kind), 38 | Tokens.scopeEmptyOrBreak(), 39 | items.map((item, i, arr) => [ 40 | i > 0 && [ 41 | Tokens.comma(), 42 | Tokens.scopeSpaceOrBreak(), 43 | ], 44 | print(item), 45 | i === arr.length - 1 && Tokens.scopeEmptyOrComma(), 46 | i === arr.length - 1 && Tokens.scopeEmptyOrBreak(), 47 | ]), 48 | Tokens.scopeClose(), 49 | ]; 50 | } 51 | 52 | /** 53 | * Prints an array of statements respecting the spacing between them. 54 | */ 55 | export function printStatements(statements, print) { 56 | if (!statements) { 57 | return null; 58 | } 59 | return statements.map((node, i, arr) => { 60 | if (i > 0) { 61 | const prevEnd = arr[i - 1].loc.end.line; 62 | 63 | // We need to find the true start, when there are comments they are not 64 | // included in the starting line of the actual node. 65 | let currStart = node.loc.start.line; 66 | if (node.leadingComments && node.leadingComments.length > 0) { 67 | currStart = node.leadingComments[0].loc.start.line; 68 | } 69 | 70 | const extra = currStart - prevEnd - 1; 71 | return [ 72 | // At max we have one extra new line, never two. 73 | extra > 0 && Tokens.string('\n'), 74 | print(node), 75 | ]; 76 | } 77 | return print(node); 78 | }); 79 | } 80 | --------------------------------------------------------------------------------