ESLint for great justice! 🚀

This commit is contained in:
Jed Fox 2017-08-05 19:17:32 -04:00
parent a0c9fa6467
commit e02b1147aa
12 changed files with 264 additions and 185 deletions

104
.eslintrc.yml Normal file
View file

@ -0,0 +1,104 @@
parser: typescript-eslint-parser
plugins:
- typescript
- babel
- react
extends:
- prettier
- prettier/react
rules:
##########
# CUSTOM #
##########
insecure-random: error
###########
# PLUGINS #
###########
# TYPESCRIPT
typescript/interface-name-prefix:
- error
- always
typescript/explicit-member-accessibility: error
typescript/no-unused-vars: error
## blocked by https://github.com/nzakas/eslint-plugin-typescript/pull/23
# typescript/member-ordering: error
##
# Babel
babel/no-invalid-this: error
babel/semi:
- error
- never
# React
react/jsx-boolean-value:
- error
- always
react/jsx-curly-spacing: error
react/jsx-equals-spacing: error
react/jsx-key: error
react/jsx-no-bind: error
react/no-string-refs: error
###########
# BUILTIN #
###########
curly: error
## blocked by https://github.com/eslint/typescript-eslint-parser/issues/344
# indent:
# - error
# - 2
# - SwitchCase: 1
##
array-bracket-spacing:
- warn
- never
object-curly-spacing:
- warn
- always
no-new-wrappers: error
no-redeclare:
- error
- builtinGlobals: true
no-eval: error
no-sync: error
no-trailing-spaces:
- error
# why?
- ignoreComments: true
no-unused-expressions: error
no-use-before-define:
- error
- functions: false
variables: false
no-var: error
prefer-const: error
no-extra-semi: error
comma-dangle:
- error
- always-multiline
eqeqeq:
- error
- smart
space-before-blocks: error
keyword-spacing: error
space-infix-ops: error
semi-spacing: error
comma-spacing: error
###########
# SPECIAL #
###########
no-restricted-syntax:
- error
# no-default-export
- selector: ExportDefaultDeclaration
message: Use of default exports is forbidden
parserOptions:
sourceType: module
ecmaFeatures:
jsx: true

180
app/npm-shrinkwrap.json generated
View file

@ -1,6 +1,6 @@
{
"name": "desktop",
"version": "0.7.3-beta1",
"version": "0.8.1-beta0",
"dependencies": {
"7zip": {
"version": "0.0.6",
@ -10,7 +10,7 @@
},
"accessibility-developer-tools": {
"version": "2.12.0",
"from": "accessibility-developer-tools@>=2.11.0 <3.0.0",
"from": "accessibility-developer-tools@^2.11.0",
"resolved": "https://registry.npmjs.org/accessibility-developer-tools/-/accessibility-developer-tools-2.12.0.tgz",
"dev": true
},
@ -25,15 +25,9 @@
"resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
"dev": true
},
"ansi-regex": {
"version": "2.1.1",
"from": "ansi-regex@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"dev": true
},
"app-path": {
"version": "2.2.0",
"from": "app-path@latest",
"from": "app-path@>=2.2.0 <3.0.0",
"resolved": "https://registry.npmjs.org/app-path/-/app-path-2.2.0.tgz"
},
"argparse": {
@ -42,9 +36,9 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz"
},
"asap": {
"version": "2.0.5",
"version": "2.0.6",
"from": "asap@>=2.0.3 <2.1.0",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz"
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
},
"asn1": {
"version": "0.2.3",
@ -101,7 +95,7 @@
},
"big.js": {
"version": "3.1.3",
"from": "big.js@>=3.1.3 <4.0.0",
"from": "big.js@^3.1.3",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
"dev": true
},
@ -218,6 +212,12 @@
}
}
},
"debug": {
"version": "2.6.8",
"from": "debug@^2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
"dev": true
},
"deep-equal": {
"version": "1.0.1",
"from": "deep-equal@>=1.0.1 <2.0.0",
@ -230,7 +230,7 @@
},
"devtron": {
"version": "1.4.0",
"from": "devtron@>=1.4.0 <2.0.0",
"from": "devtron@^1.4.0",
"resolved": "https://registry.npmjs.org/devtron/-/devtron-1.4.0.tgz",
"dev": true
},
@ -256,8 +256,20 @@
},
"dugite": {
"version": "1.38.0",
"from": "dugite@1.38.0",
"resolved": "https://registry.npmjs.org/dugite/-/dugite-1.38.0.tgz"
"from": "dugite@>=1.38.0 <2.0.0",
"resolved": "https://registry.npmjs.org/dugite/-/dugite-1.38.0.tgz",
"dependencies": {
"http-signature": {
"version": "1.1.1",
"from": "http-signature@>=1.1.0 <1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz"
},
"request": {
"version": "2.81.0",
"from": "request@>=2.79.0 <3.0.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz"
}
}
},
"ecc-jsbn": {
"version": "0.1.1",
@ -266,27 +278,33 @@
"optional": true
},
"electron-debug": {
"version": "1.1.0",
"from": "electron-debug@>=1.1.0 <2.0.0",
"resolved": "https://registry.npmjs.org/electron-debug/-/electron-debug-1.1.0.tgz",
"version": "1.3.0",
"from": "electron-debug@^1.1.0",
"resolved": "https://registry.npmjs.org/electron-debug/-/electron-debug-1.3.0.tgz",
"dev": true
},
"electron-devtools-installer": {
"version": "2.2.0",
"from": "electron-devtools-installer@>=2.1.0 <3.0.0",
"from": "electron-devtools-installer@^2.1.0",
"resolved": "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-2.2.0.tgz",
"dev": true
},
"electron-is-dev": {
"electron-is-accelerator": {
"version": "0.1.2",
"from": "electron-is-dev@>=0.1.0 <0.2.0",
"resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz",
"from": "electron-is-accelerator@^0.1.0",
"resolved": "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz",
"dev": true
},
"electron-is-dev": {
"version": "0.3.0",
"from": "electron-is-dev@^0.3.0",
"resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.3.0.tgz",
"dev": true
},
"electron-localshortcut": {
"version": "0.6.1",
"from": "electron-localshortcut@>=0.6.0 <0.7.0",
"resolved": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-0.6.1.tgz",
"version": "2.0.2",
"from": "electron-localshortcut@^2.0.0",
"resolved": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-2.0.2.tgz",
"dev": true
},
"electron-window-state": {
@ -296,7 +314,7 @@
},
"emojis-list": {
"version": "2.1.0",
"from": "emojis-list@>=2.0.0 <3.0.0",
"from": "emojis-list@^2.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
"dev": true
},
@ -336,13 +354,13 @@
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz"
},
"fbjs": {
"version": "0.8.12",
"version": "0.8.14",
"from": "fbjs@>=0.8.9 <0.9.0",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz"
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz"
},
"file-uri-to-path": {
"version": "0.0.2",
"from": "file-uri-to-path@latest",
"from": "file-uri-to-path@0.0.2",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-0.0.2.tgz"
},
"forever-agent": {
@ -370,11 +388,6 @@
"from": "fs.realpath@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"fstream": {
"version": "1.0.11",
"from": "fstream@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz"
},
"getpass": {
"version": "0.1.7",
"from": "getpass@>=0.1.1 <0.2.0",
@ -413,9 +426,9 @@
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz"
},
"highlight.js": {
"version": "9.11.0",
"from": "highlight.js@>=9.3.0 <10.0.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.11.0.tgz",
"version": "9.12.0",
"from": "highlight.js@^9.3.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz",
"dev": true
},
"hoek": {
@ -425,25 +438,20 @@
},
"html-entities": {
"version": "1.2.1",
"from": "html-entities@>=1.2.0 <2.0.0",
"from": "html-entities@^1.2.0",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
"dev": true
},
"http-signature": {
"version": "1.1.1",
"from": "http-signature@>=1.1.0 <1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz"
},
"humanize-plus": {
"version": "1.8.2",
"from": "humanize-plus@>=1.8.1 <2.0.0",
"from": "humanize-plus@^1.8.1",
"resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz",
"dev": true
},
"iconv-lite": {
"version": "0.4.17",
"version": "0.4.18",
"from": "iconv-lite@>=0.4.13 <0.5.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz"
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz"
},
"inflight": {
"version": "1.0.6",
@ -481,9 +489,9 @@
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz"
},
"js-tokens": {
"version": "3.0.1",
"version": "3.0.2",
"from": "js-tokens@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz"
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz"
},
"js-yaml": {
"version": "3.8.3",
@ -513,7 +521,7 @@
},
"json5": {
"version": "0.5.1",
"from": "json5@>=0.5.0 <0.6.0",
"from": "json5@^0.5.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"dev": true
},
@ -546,7 +554,7 @@
},
"loader-utils": {
"version": "1.1.0",
"from": "loader-utils@>=1.0.2 <2.0.0",
"from": "loader-utils@^1.0.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"dev": true
},
@ -595,15 +603,21 @@
"from": "moment@>=2.17.1 <3.0.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz"
},
"ms": {
"version": "2.0.0",
"from": "ms@2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"dev": true
},
"nan": {
"version": "2.5.1",
"from": "nan@2.5.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz"
},
"node-fetch": {
"version": "1.6.3",
"version": "1.7.1",
"from": "node-fetch@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz"
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz"
},
"npm-run-path": {
"version": "1.0.0",
@ -661,9 +675,9 @@
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz"
},
"promise": {
"version": "7.1.1",
"version": "7.3.1",
"from": "promise@>=7.1.1 <8.0.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz"
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz"
},
"prop-types": {
"version": "15.5.10",
@ -687,7 +701,7 @@
},
"querystring": {
"version": "0.2.0",
"from": "querystring@>=0.2.0 <0.3.0",
"from": "querystring@^0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"dev": true
},
@ -698,7 +712,7 @@
},
"react-addons-perf": {
"version": "15.4.2",
"from": "react-addons-perf@>=15.4.2 <16.0.0",
"from": "react-addons-perf@15.4.2",
"resolved": "https://registry.npmjs.org/react-addons-perf/-/react-addons-perf-15.4.2.tgz",
"dev": true
},
@ -733,11 +747,6 @@
"from": "regenerator-runtime@>=0.10.0 <0.11.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz"
},
"request": {
"version": "2.81.0",
"from": "request@>=2.79.0 <3.0.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz"
},
"rimraf": {
"version": "2.6.1",
"from": "rimraf@>=2.5.4 <3.0.0",
@ -754,9 +763,9 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz"
},
"semver": {
"version": "5.3.0",
"from": "semver@>=5.3.0 <6.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"version": "5.4.1",
"from": "semver@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0||>=4.0.0 <5.0.0||>=5.0.0 <6.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"dev": true
},
"setimmediate": {
@ -806,12 +815,6 @@
"from": "stringstream@>=0.0.4 <0.1.0",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
},
"strip-ansi": {
"version": "3.0.1",
"from": "strip-ansi@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dev": true
},
"strip-eof": {
"version": "1.0.0",
"from": "strip-eof@>=1.0.0 <2.0.0",
@ -819,24 +822,31 @@
},
"style-loader": {
"version": "0.13.2",
"from": "style-loader@>=0.13.2 <0.14.0",
"from": "style-loader@^0.13.2",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz",
"dev": true
},
"tar": {
"version": "2.2.1",
"from": "tar@>=2.2.1 <3.0.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz"
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
"dependencies": {
"fstream": {
"version": "1.0.11",
"from": "fstream@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz"
}
}
},
"temp": {
"version": "0.8.3",
"from": "temp@>=0.8.3 <0.9.0",
"from": "temp@^0.8.3",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
"dev": true,
"dependencies": {
"rimraf": {
"version": "2.2.8",
"from": "rimraf@>=2.2.6 <2.3.0",
"from": "rimraf@~2.2.6",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
"dev": true
}
@ -901,10 +911,24 @@
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz"
},
"webpack-hot-middleware": {
"version": "2.18.0",
"from": "webpack-hot-middleware@>=2.10.0 <3.0.0",
"resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.18.0.tgz",
"dev": true
"version": "2.18.2",
"from": "webpack-hot-middleware@^2.10.0",
"resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.18.2.tgz",
"dev": true,
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"from": "ansi-regex@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"dev": true
},
"strip-ansi": {
"version": "3.0.1",
"from": "strip-ansi@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dev": true
}
}
},
"whatwg-fetch": {
"version": "2.0.3",

View file

@ -149,7 +149,7 @@ function skewInterval(): number {
// We don't need cryptographically secure random numbers for
// the skew. Pseudo-random should be just fine.
// tslint:disable-next-line:insecure-random
// eslint-disable-next-line insecure-random
const skew = Math.ceil(Math.random() * SkewUpperBound)
_skewInterval = skew
return skew

View file

@ -177,7 +177,7 @@ declare const log: IDesktopLogger
// these changes should be pushed into the Electron declarations
declare namespace NodeJS {
// tslint:disable-next-line:interface-name
// eslint-disable-next-line typescript/interface-name-prefix
interface Process extends EventEmitter {
once(event: 'uncaughtException', listener: (error: Error) => void): this
on(event: 'uncaughtException', listener: (error: Error) => void): this
@ -187,7 +187,7 @@ declare namespace NodeJS {
}
declare namespace Electron {
// tslint:disable-next-line:interface-name
// eslint-disable-next-line typescript/interface-name-prefix
interface MenuItem {
readonly accelerator?: Electron.Accelerator
readonly submenu?: Electron.Menu
@ -195,7 +195,7 @@ declare namespace Electron {
readonly type: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'
}
// tslint:disable-next-line:interface-name
// eslint-disable-next-line typescript/interface-name-prefix
interface RequestOptions {
readonly method: string
readonly url: string
@ -204,7 +204,7 @@ declare namespace Electron {
type AppleActionOnDoubleClickPref = 'Maximize' | 'Minimize' | 'None'
// tslint:disable-next-line:interface-name
// eslint-disable-next-line typescript/interface-name-prefix
interface SystemPreferences {
getUserDefault(
key: 'AppleActionOnDoubleClick',

View file

@ -48,13 +48,13 @@ function retrieveSourceMap(source: string) {
// https://github.com/v8/v8/wiki/Stack-Trace-API#customizing-stack-traces
// This happens on-demand when someone accesses the stack
// property on an error object and has to be synchronous :/
// tslint:disable-next-line:no-sync-functions
// eslint-disable-next-line no-sync
if (!Fs.existsSync(path)) {
return
}
try {
// tslint:disable-next-line:no-sync-functions
// eslint-disable-next-line no-sync
const map = Fs.readFileSync(path, 'utf8')
return { url: Path.basename(path), map }
} catch (error) {
@ -125,8 +125,7 @@ function sourceMappedStackTrace(error: Error): string | undefined {
// in our weak map. In order to get around that we'll eagerly access the
// stack, forcing our handler to run which should ensure that the native
// frames are stored in our weak map.
// tslint:disable-next-line:whitespace
;(error.stack || '').toString()
(error.stack || '').toString()
frames = stackFrameMap.get(error)
}

View file

@ -182,8 +182,7 @@ export class Dialog extends React.Component<IDialogProps, IDialogState> {
public componentDidMount() {
// This cast to any is necessary since React doesn't know about the
// dialog element yet.
// tslint:disable-next-line:whitespace
;(this.dialogElement as any).showModal()
(this.dialogElement as any).showModal()
this.setState({ isAppearing: true })
this.scheduleDismissGraceTimeout()

View file

@ -177,7 +177,7 @@ class UpdateStore {
public quitAndInstallUpdate() {
// This is synchronous so that we can ensure the app will let itself be quit
// before we call the function to quit.
// tslint:disable-next-line:no-sync-functions
// eslint-disable-next-line no-sync
sendWillQuitSync()
autoUpdater.quitAndInstall()
}

View file

@ -40,7 +40,7 @@ export function showCertificateTrustDialog(
* that would tell the app to quit.
*/
export function sendWillQuitSync() {
// tslint:disable-next-line:no-sync-functions
// eslint-disable-next-line no-sync
ipcRenderer.sendSync('will-quit')
}

View file

@ -0,0 +1,34 @@
// strings from https://github.com/Microsoft/tslint-microsoft-contrib/blob/b720cd9/src/insecureRandomRule.ts
const MATH_FAIL_STRING =
"Math.random produces insecure random numbers. " +
"Use crypto.randomBytes() or window.crypto.getRandomValues() instead";
const NODE_FAIL_STRING =
"crypto.pseudoRandomBytes produces insecure random numbers. " + "Use crypto.randomBytes() instead";
module.exports = {
meta: {
docs: {
description: 'Do not use insecure sources for random bytes',
category: 'Best Practices',
}
},
create(context) {
return {
CallExpression(node) {
const { callee } = node;
const isMemberExpression = callee.type === "MemberExpression";
if (isMemberExpression && callee.object.name === "Math" && callee.property.name === "random") {
context.report(node, MATH_FAIL_STRING);
}
if (
(isMemberExpression && callee.property.name === "pseudoRandomBytes") ||
callee.name === "pseudoRandomBytes"
) {
context.report(node, NODE_FAIL_STRING);
}
}
}
}
}

View file

@ -21,7 +21,10 @@
"package": "node script/package",
"clean:tslint": "rimraf tslint-rules/*.js",
"compile:tslint": "tsc -p tslint-rules",
"lint": "npm run compile:tslint && tslint \"./app/{src,test}/**/*.{ts,tsx}\"",
"lint": "npm run compile:tslint && npm run tslint && npm run eslint-check && npm run eslint",
"tslint": "tslint ./app/{src,tslint-rules,typings,test}/**/*.{ts,tsx}",
"eslint": "eslint --rulesdir ./eslint-rules ./app/{src,{e,t}slint-rules,typings,test}/**/*.{js,ts,tsx}",
"eslint-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check",
"check-prettiness": "node script/is-it-pretty",
"publish": "node script/publish",
"clean-slate": "rimraf out node_modules app/node_modules && npm install",
@ -56,6 +59,11 @@
"electron-mocha": "3.5.0",
"electron-packager": "^8.7.2",
"electron-winstaller": "2.5.2",
"eslint": "^4.3.0",
"eslint-config-prettier": "^2.3.0",
"eslint-plugin-babel": "^4.1.2",
"eslint-plugin-react": "^7.1.0",
"eslint-plugin-typescript": "^0.3.0",
"express": "^4.15.0",
"extract-text-webpack-plugin": "^2.1.0",
"fs-extra": "^2.1.2",
@ -77,7 +85,8 @@
"ts-node": "^3.2.0",
"tslint": "^4.5.1",
"tslint-microsoft-contrib": "^4.0.1",
"typescript": "2.4.1",
"typescript": "^2.4.1",
"typescript-eslint-parser": "^5.0.0",
"vrsource-tslint-rules": "^0.12.0",
"webpack": "^2.4.1",
"webpack-dev-middleware": "^1.10.1",

View file

@ -1,39 +0,0 @@
/**
* no-sync-functions
*
* Don't allow calling any functions that end in 'Sync'.
*/
import * as ts from 'typescript'
import * as Lint from 'tslint'
export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoSyncFunctionsWalker(sourceFile, this.getOptions()))
}
}
// The walker takes care of all the work.
class NoSyncFunctionsWalker extends Lint.RuleWalker {
protected visitCallExpression(node: ts.CallExpression): void {
const functionName = this.getFunctionName(node)
if (functionName && functionName.endsWith('Sync')) {
const start = node.getStart()
const width = node.getWidth()
const error = `Synchronous functions shouldn't be used. Find an asynchronous alternative.`
this.addFailure(this.createFailure(start, width, error))
} else {
super.visitCallExpression(node)
}
}
// Taken from https://github.com/Microsoft/tslint-microsoft-contrib/blob/051abda5bafffd8068c42bdc9da7afc488cfab76/src/utils/AstUtils.ts#L16-L23.
private getFunctionName(node: ts.CallExpression): string {
const expression: ts.Expression = node.expression
let functionName: string = (expression as any).text
if (functionName === undefined && (expression as any).name) {
functionName = (expression as any).name.text
}
return functionName
}
}

View file

@ -1,9 +1,9 @@
{
"extends": [
"tslint-react",
"tslint-config-prettier"
],
"rulesDirectory": [
"node_modules/tslint-react/rules",
"node_modules/vrsource-tslint-rules/rules",
"node_modules/tslint-microsoft-contrib/",
"tslint-rules/"
@ -11,50 +11,18 @@
"rules": {
"button-group-order": true,
"class-name": true,
"curly": true,
"indent": [
true,
"spaces"
],
"insecure-random": [ true ],
"interface-name": [ true, "always-prefix"],
"jsdoc-format": true,
"literal-spacing": [
false,
{
"array": ["never"],
"object": ["always"]
}
],
"member-access": [
true,
"check-accessor",
"check-constructor"
],
"jsx-no-multiline-js": true,
"member-ordering": [
true,
"static-before-instance",
"variables-before-functions"
],
"no-construct": true,
"no-default-export": true,
"no-duplicate-variable": true,
"no-eval": true,
"no-internal-module": true,
"no-invalid-this": true,
"no-stateless-class": true,
"no-sync-functions": true,
"no-trailing-whitespace": [ true, "ignore-comments", "ignore-jsdoc" ],
"no-unused-expression": true,
"no-unused-variable": [true, "react"],
"no-use-before-declare": true,
"no-var-keyword": true,
"one-line": [
true,
"check-open-brace",
"check-whitespace"
],
"prefer-const": true,
"promise-must-complete": true,
"react-no-unbound-dispatcher-props": true,
"react-proper-lifecycle-methods": true,
@ -66,21 +34,6 @@
}
],
"react-this-binding-issue": true,
"semicolon": [
true,
"never"
],
"trailing-comma": [
false,
{
"multiline": "always",
"singleline": "never"
}
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
@ -97,10 +50,6 @@
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}