├── package.json ├── README.md └── index.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-flowtype", 3 | "version": "1.0.0", 4 | "description": "ESLint checking of files containing FlowType annotations", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "eslint", 11 | "plugin", 12 | "eslintplugin", 13 | "flowtype" 14 | ], 15 | "peerDependencies": { 16 | "eslint": ">=0.20.0" 17 | }, 18 | "files": [ 19 | "README.md", 20 | "index.js" 21 | ], 22 | "homepage": "https://github.com/gcazaciuc/eslint-plugin-flowtype", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/gcazaciuc/eslint-plugin-flowtype.git" 26 | }, 27 | "author": "Cazaciuc Gabriel", 28 | "license": "MIT", 29 | "dependencies": { 30 | "esprima-fb": "^15001.1.0-dev-harmony-fb", 31 | "recast": "^0.10.13", 32 | "source-map": "^0.4.2" 33 | }, 34 | "engines": { 35 | "node": ">= 0.8" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eslint-plugin-flowtype 2 | A plugin for ESLint that strips FlowType type annonations before linting the files. 3 | 4 | If your code uses flow type annotations ( http://flowtype.org/ ) and you would like to lint it using ESLint currently the only option is using babel-eslint as ESLint parser instead of the default Espree. 5 | 6 | However, Babel-Eslint currently monkey patches ESLint and I had lots of issues with upgrading to newer versions of ESlint and Babel-Eslint. 7 | 8 | This plugins strips the type annotations before handing off the file for linting as such you are able to use the latest and greates ESLint parser: Espree on FlowType'd code. 9 | 10 | Internally the plugin makes use of Recast for performing AST transforms and stripping the annotations together with esprima-fb parser( which is now deprecated but i couldn't get flow-parser to play nice with recast as such had to use esprima ). 11 | 12 | The plugin also preserves the line numbers by using Recast source maps. 13 | 14 | # Configuration 15 | Enable the plugin in eslint.rc file by adding it to the plugins section: 16 | 17 | plugins: ["flowtype"] 18 | 19 | # Know issues 20 | Issues with max-len ESlint rule reporting the line/column number as "0:0" 21 | 22 | # TO DO: 23 | Investigate the use of flow-parser for parsing the source code and stripping out any annotations. Currently the problem is that we cannot get Recast to play nice with "flow-parser". 24 | I would appreciate any help on this matter. 25 | 26 | # Thanks 27 | Many thanks to fkling ( https://github.com/fkling/flow-typestrip ) for writing up the type annotation striping logic. 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var recast = require('recast'); 2 | var types = recast.types; 3 | 4 | var currentInfos = null; 5 | 6 | function remove(path) { 7 | path.replace(); 8 | return false; 9 | } 10 | 11 | function transformClass(path) { 12 | path.get('typeParameters').replace(); 13 | path.get('superTypeParameters').replace(); 14 | path.get('implements').replace(); 15 | this.traverse(path); 16 | } 17 | 18 | function transformPattern(path) { 19 | path.get('typeAnnotation').replace(); 20 | this.traverse(path); 21 | } 22 | 23 | 24 | /** 25 | * Compile the given Flow typed JavaScript source into JavaScript usable in 26 | * today's runtime environments. 27 | * 28 | * @param {string} source 29 | * @param {object} options 30 | * @return {{code:string, map:string}} 31 | */ 32 | function compile(source, options) { 33 | if (!options) { options = {}; } 34 | var ast = recast.parse(source, { 35 | esprima: require('esprima-fb'), 36 | sourceFileName: options.souceFileName 37 | }); 38 | ast = transform(ast, options); 39 | return recast.print(ast, { 40 | "sourceMapName": options.sourceMapName 41 | }); 42 | } 43 | 44 | /** 45 | * Transform the given typed JavaScript AST into a JavaScript AST 46 | * usable in today's runtime environments. 47 | * 48 | * @param {object} ast 49 | * @return {object} 50 | */ 51 | function transform(ast) { 52 | 53 | types.visit(ast, { 54 | visitIdentifier: function(path) { 55 | path.get('optional').replace(); 56 | path.get('typeAnnotation').replace(); 57 | return false; 58 | }, 59 | visitFunction: function(path) { 60 | path.get('returnType').replace(); 61 | path.get('typeParameters').replace(); 62 | this.traverse(path); 63 | }, 64 | visitClassDeclaration: transformClass, 65 | visitClassExpression: transformClass, 66 | visitArrayPattern: transformPattern, 67 | visitObjectPattern: transformPattern, 68 | visitTypeAnnotation: remove, 69 | visitClassImplements: remove, 70 | visitClassProperty: remove, 71 | visitInterfaceDeclaration: remove, 72 | visitTypeAlias: remove, 73 | visitDeclareVariable: remove, 74 | visitDeclareFunction: remove, 75 | visitDeclareClass: remove, 76 | visitDeclareModule: remove, 77 | visitType: remove, 78 | }); 79 | 80 | return ast; 81 | } 82 | 83 | var flowTypePreprocessor = { 84 | preprocess: function(text, filename) { 85 | currentInfos = compile(text, {souceFileName: filename, sourceMapName: "map.json"}); 86 | return [currentInfos.code]; 87 | }, 88 | postprocess: function(messages) { 89 | var map = currentInfos.map; 90 | var SourceMapConsumer = require("source-map").SourceMapConsumer; 91 | var smc = new SourceMapConsumer(map); 92 | messages[0].forEach(function (message) { 93 | var originalPos = smc.originalPositionFor({ 94 | line: message.line, 95 | column: message.column 96 | }); 97 | message.line = originalPos.line; 98 | message.column = originalPos.column; 99 | }); 100 | return messages[0]; 101 | } 102 | }; 103 | 104 | module.exports = { 105 | rules: { 106 | "dummyrule": function (context) { 107 | // rule implementation ... 108 | } 109 | }, 110 | processors: { 111 | ".jsx": flowTypePreprocessor, 112 | ".js": flowTypePreprocessor, 113 | ".es6": flowTypePreprocessor 114 | } 115 | }; 116 | --------------------------------------------------------------------------------