-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* added ts-config-include to src/rules * added ts-config-include to tests/rules * added new rules ts-config-include * Create ts-config-include.md * run rushx format to fix README.md, ts-config-include.ts, and ts-package-json-engine-is-present.ts * Fixed the broken README.md * Fixed the broken README.md 2 * Revert prettier formatting on ts-package-json-engine-is-present.ts * simplified checking and fixed wording in src/rules/ts-config-include.ts
- Loading branch information
Showing
8 changed files
with
306 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
common/tools/eslint-plugin-azure-sdk/docs/rules/ts-config-include.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
> docs\rules\ts-config-include.md | ||
# ts-config-include | ||
|
||
Requires `include` in `tsconfig.json` to at least include `src/**/*.ts`, `test/**/*.ts`, and `samples-dev/**/*.ts`. | ||
|
||
This rule is fixable using the `--fix` option. | ||
|
||
## Examples | ||
|
||
### Good | ||
|
||
```json | ||
{ | ||
"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts", "other/*.ts"] | ||
} | ||
``` | ||
|
||
### Bad | ||
|
||
```json | ||
{ | ||
"include": ["src/**/*.ts", "test/**/*.ts"] | ||
} | ||
``` | ||
|
||
```json | ||
{ | ||
"include": [] | ||
} | ||
``` | ||
|
||
```json | ||
{} | ||
``` | ||
|
||
## When to turn off | ||
|
||
Only if the rule breaks. | ||
|
||
## [Source](https://azure.github.io/azure-sdk/typescript_design.html#ts-config-include) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
common/tools/eslint-plugin-azure-sdk/src/rules/ts-config-include.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
/** | ||
* @file Rule to force tsconfig.json's "include" value to at least contain "src/**\/*.ts", "test/**\/*.ts", and "samples-dev/**\/*.ts" | ||
* @author Wei Jun Tan | ||
*/ | ||
|
||
import { Rule } from "eslint"; | ||
import { ArrayExpression, Literal, Property } from "estree"; | ||
import { arrayToString, getRuleMetaData, getVerifiers, stripPath } from "../utils"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
export = { | ||
meta: getRuleMetaData( | ||
"ts-config-include", | ||
"force tsconfig.json's 'include' value to at least contain 'src/**/*.ts', 'test/**/*.ts', and 'samples-dev/**/*.ts'", | ||
"code" | ||
), | ||
create: (context: Rule.RuleContext): Rule.RuleListener => { | ||
const verifiers = getVerifiers(context, { | ||
outer: "include" | ||
}); | ||
return stripPath(context.getFilename()) === "tsconfig.json" | ||
? ({ | ||
// callback functions | ||
|
||
// check to see if include exists at the outermost level | ||
"ExpressionStatement > ObjectExpression": verifiers.existsInFile, | ||
|
||
// check the node corresponding to include to see if its value contains "src/**/*.ts", "test/**/*.ts", and "samples-dev/**/*.ts" | ||
"ExpressionStatement > ObjectExpression > Property[key.value='include']": ( | ||
node: Property | ||
): void => { | ||
// check if the value is an array of literals | ||
if (node.value.type !== "ArrayExpression") { | ||
context.report({ | ||
node: node.value, | ||
message: `include is not set to an array` | ||
}); | ||
} | ||
|
||
const nodeValue = node.value as ArrayExpression; | ||
|
||
const nonLiteral = nodeValue.elements.find( | ||
(element: any): boolean => element.type !== "Literal" | ||
); | ||
|
||
if (nonLiteral !== undefined && nonLiteral !== null) { | ||
context.report({ | ||
node: nonLiteral, | ||
message: `include contains non-literal elements, literal strings are expected instead` | ||
}); | ||
} | ||
|
||
const expected = ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]; | ||
const candidateArray = nodeValue.elements as Literal[]; | ||
const candidateValues = candidateArray.map( | ||
(candidate: Literal): unknown => candidate.value | ||
); | ||
|
||
// Check if the expected values is included in the array | ||
expected.forEach((value: unknown): void => { | ||
if (!candidateValues.includes(value)) { | ||
candidateValues.push(value); | ||
} | ||
}); | ||
if (candidateValues.length > candidateArray.length) { | ||
context.report({ | ||
node: nodeValue, | ||
message: `include does not contain ${arrayToString(candidateValues)}`, | ||
fix: (fixer: Rule.RuleFixer): Rule.Fix => | ||
fixer.replaceText(nodeValue, arrayToString(candidateValues)) | ||
}); | ||
} | ||
} | ||
} as Rule.RuleListener) | ||
: {}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
common/tools/eslint-plugin-azure-sdk/tests/rules/ts-config-include.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
/** | ||
* @file Testing the ts-config-include rule. | ||
* @author Wei Jun Tan | ||
*/ | ||
|
||
import rule from "../../src/rules/ts-config-include"; | ||
import { RuleTester } from "eslint"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Example files | ||
//------------------------------------------------------------------------------ | ||
|
||
const exampleTsconfigGood = `{ | ||
"compilerOptions": { | ||
/* Basic Options */ | ||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, | ||
"module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, | ||
"declaration": true /* Generates corresponding '.d.ts' file. */, | ||
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, | ||
"sourceMap": true /* Generates corresponding '.map' file. */, | ||
"outDir": "./dist-esm" /* Redirect output structure to the directory. */, | ||
"declarationDir": "./typings" /* Output directory for generated declaration files.*/, | ||
"importHelpers": true /* Import emit helpers from 'tslib'. */, | ||
/* Strict Type-Checking Options */ | ||
"strict": true /* Enable all strict type-checking options. */, | ||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */, | ||
/* Additional Checks */ | ||
"noUnusedLocals": true /* Report errors on unused locals. */, | ||
/* Module Resolution Options */ | ||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, | ||
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, | ||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, | ||
/* Experimental Options */ | ||
"forceConsistentCasingInFileNames": true, | ||
/* Other options */ | ||
"newLine": "LF" /* Use the specified end of line sequence to be used when emitting files: "crlf" (windows) or "lf" (unix).”*/, | ||
"allowJs": false /* Don't allow JavaScript files to be compiled.*/, | ||
"resolveJsonModule": true | ||
}, | ||
"compileOnSave": true, | ||
"exclude": ["typings/**", "./samples/**/*.ts", "node_modules"], | ||
"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"] | ||
}`; | ||
|
||
const exampleTsconfigBad = `{ | ||
"compilerOptions": { | ||
/* Basic Options */ | ||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, | ||
"module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, | ||
"declaration": true /* Generates corresponding '.d.ts' file. */, | ||
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, | ||
"sourceMap": true /* Generates corresponding '.map' file. */, | ||
"outDir": "./dist-esm" /* Redirect output structure to the directory. */, | ||
"declarationDir": "./typings" /* Output directory for generated declaration files.*/, | ||
"importHelpers": true /* Import emit helpers from 'tslib'. */, | ||
/* Strict Type-Checking Options */ | ||
"strict": true /* Enable all strict type-checking options. */, | ||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */, | ||
/* Additional Checks */ | ||
"noUnusedLocals": true /* Report errors on unused locals. */, | ||
/* Module Resolution Options */ | ||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, | ||
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, | ||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, | ||
/* Experimental Options */ | ||
"forceConsistentCasingInFileNames": true, | ||
/* Other options */ | ||
"newLine": "LF" /* Use the specified end of line sequence to be used when emitting files: "crlf" (windows) or "lf" (unix).”*/, | ||
"allowJs": false /* Don't allow JavaScript files to be compiled.*/, | ||
"resolveJsonModule": true | ||
}, | ||
"compileOnSave": true, | ||
"exclude": ["typings/**", "./samples/**/*.ts", "node_modules"], | ||
"include": [] | ||
}`; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Tests | ||
//------------------------------------------------------------------------------ | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: require.resolve("@typescript-eslint/parser"), | ||
parserOptions: { | ||
createDefaultProgram: true, | ||
project: "./tsconfig.json" | ||
} | ||
}); | ||
|
||
ruleTester.run("ts-config-include", rule, { | ||
valid: [ | ||
{ | ||
// only the fields we care about | ||
code: '{"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]}', | ||
filename: "tsconfig.json" | ||
}, | ||
{ | ||
// a full example tsconfig.json | ||
code: exampleTsconfigGood, | ||
filename: "tsconfig.json" | ||
}, | ||
{ | ||
// incorrect format but in a file we don't care about | ||
code: '{"include": []}', | ||
filename: "not_tsconfig.json" | ||
} | ||
], | ||
invalid: [ | ||
{ | ||
code: '{"notInclude": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]}', | ||
filename: "tsconfig.json", | ||
errors: [ | ||
{ | ||
message: "include does not exist at the outermost level" | ||
} | ||
] | ||
}, | ||
{ | ||
// exclude is in a nested object | ||
code: '{"outer": {"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]}}', | ||
filename: "tsconfig.json", | ||
errors: [ | ||
{ | ||
message: "include does not exist at the outermost level" | ||
} | ||
] | ||
}, | ||
{ | ||
// only the fields we care about | ||
code: '{"include": []}', | ||
filename: "tsconfig.json", | ||
errors: [ | ||
{ | ||
message: 'include does not contain ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]' | ||
} | ||
], | ||
output: '{"include": ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]}' | ||
}, | ||
{ | ||
// example file with empty include | ||
code: exampleTsconfigBad, | ||
filename: "tsconfig.json", | ||
errors: [ | ||
{ | ||
message: 'include does not contain ["src/**/*.ts", "test/**/*.ts", "samples-dev/**/*.ts"]' | ||
} | ||
], | ||
output: exampleTsconfigGood | ||
} | ||
] | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters