error for I prefixed interface names

Summary: {gif:kosnw403}

Reviewed By: mweststrate

Differential Revision: D33845782

fbshipit-source-id: 2b9bd70e3b2d930e8f4cd8fe7976ac76f43b2496
This commit is contained in:
Anton Kastritskiy
2022-01-31 05:33:49 -08:00
committed by Facebook GitHub Bot
parent a0368a8bbf
commit 75f874a5dd
5 changed files with 98 additions and 1 deletions

View File

@@ -145,6 +145,7 @@ module.exports = {
'flipper/no-electron-remote-imports': [1], 'flipper/no-electron-remote-imports': [1],
'flipper/no-console-error-without-context': [2], 'flipper/no-console-error-without-context': [2],
'flipper/no-ts-file-extension': 1, 'flipper/no-ts-file-extension': 1,
'flipper/no-i-prefix-interfaces': 2,
'communist-spelling/communist-spelling': [1, {allow: ['cancelled']}], 'communist-spelling/communist-spelling': [1, {allow: ['cancelled']}],
// promise rules, see https://github.com/xjamundx/eslint-plugin-promise for details on each of them // promise rules, see https://github.com/xjamundx/eslint-plugin-promise for details on each of them

View File

@@ -19,6 +19,9 @@ import noConsoleErrorWithoutContext, {
import noTsFileExtension, { import noTsFileExtension, {
RULE_NAME as noTsFileExtensionRuleName, RULE_NAME as noTsFileExtensionRuleName,
} from './rules/noTsFileExtension'; } from './rules/noTsFileExtension';
import noIPrefixInterfaces, {
RULE_NAME as noIPrefixInterfacesRuleName,
} from './rules/noIPrefixInterfaces';
module.exports = { module.exports = {
rules: { rules: {
@@ -26,5 +29,6 @@ module.exports = {
[noElectronRemoteImportsRuleName]: noElectronRemoteImports, [noElectronRemoteImportsRuleName]: noElectronRemoteImports,
[noConsoleErrorWithoutContextRuleName]: noConsoleErrorWithoutContext, [noConsoleErrorWithoutContextRuleName]: noConsoleErrorWithoutContext,
[noTsFileExtensionRuleName]: noTsFileExtension, [noTsFileExtensionRuleName]: noTsFileExtension,
[noIPrefixInterfacesRuleName]: noIPrefixInterfaces,
}, },
}; };

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {TSESLint} from '@typescript-eslint/experimental-utils';
import rule, {RULE_NAME} from '../noIPrefixInterfaces';
const tester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
},
});
tester.run(RULE_NAME, rule, {
valid: [
{
code: `interface Icon {name: string}`,
filename: __filename,
},
{
code: `interface IOSDevice {version: string}`,
filename: __filename,
},
],
invalid: [
{
code: `interface IDevice {version: string;}`,
filename: __filename,
errors: [{messageId: 'noTsInterfacePrefixI'}],
},
],
});

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {createESLintRule} from '../utils/createEslintRule';
type Options = [];
export type MessageIds = 'noTsInterfacePrefixI';
export const RULE_NAME = 'no-i-prefix-interfaces';
export default createESLintRule<Options, MessageIds>({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: 'Avoid prefixing TS interfaces with "I"',
recommended: 'error',
},
schema: [],
messages: {
noTsInterfacePrefixI: 'Do not prefix interfaces with "I"',
},
},
defaultOptions: [],
create(context) {
return {
TSInterfaceDeclaration(node) {
const [l1, l2, l3] = node.id.name;
if (
l1 === 'I' &&
isLetter(l2) &&
l2 === l2.toUpperCase() &&
isLetter(l3) &&
l3 === l3.toLowerCase()
) {
context.report({
node: node.id,
messageId: 'noTsInterfacePrefixI',
});
}
},
};
},
});
function isLetter(x: string | undefined): boolean {
return typeof x === 'string' && /^[a-z]$/i.test(x);
}

View File

@@ -159,7 +159,6 @@ To start Flipper against a specific OnDemand instance, set FB_ONDEMAND flag, e.g
## Guidelines for writing TypeScript ## Guidelines for writing TypeScript
* Prefer `type` for React props and state over interfaces * Prefer `type` for React props and state over interfaces
* Dont prefix interfaces with `I`
* Install 3rd party type definitions as dev dependency (e.g. `yarn add @types/lodash --dev`) * Install 3rd party type definitions as dev dependency (e.g. `yarn add @types/lodash --dev`)
## Submitting a diff / PR ## Submitting a diff / PR