Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Revamped configs into 'core', 'latest', and (legacy) 'recommended' #809

Merged
merged 7 commits into from
Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
.npm_cache
node_modules
npm-debug.log

# TypeScrit temporary/cache files
**/.baseDir.ts
**/.tscache/
tscommand-*.tmp.txt

# Generated for builds
**/dist/

# IDEA
.idea
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
tslint-microsoft-contrib.iml

# vim swap files
*.sw*

**/tags

# local npm cache
.npm_cache

out.html
rule-metadata.json
6 changes: 3 additions & 3 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Build directory
dist/

# Configuration settings
configs/

# Definition files
*.d.ts

Expand All @@ -10,6 +13,3 @@ package-lock.json

# Test files
test-data/NoUnnecessarySemicolonsTestInput.ts

# Generated files
recommended_ruleset.js
52 changes: 43 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,57 @@ Add `"node_modules/tslint-microsoft-contrib"` under your `"rulesDirectory"` conf
### Which Rules Should I Turn On?

There certainly are a lot of options!
To start, you can enable our recommended defaults ([recommended_ruleset.js](recommended_ruleset.js)) by adding `"tslint-microsoft-contrib"` under `"extends"` in your `tslint.json`:

If you extend from one of the following configurations, `rulesDirectory` will have `node_modules/tslint-microsoft-contrib` included for you.

> Please note, some of the default ruleset rules require the `--project` TSLint option.

#### Stable

To start, you can enable our "stable" defaults that come with tslint-microsoft-contrib ([configs/stable.json](./configs/stable.json)) by adding `"tslint-microsoft-contrib/configs/stable"` under `"extends"` in your `tslint.json`:

```json
{
"extends": ["tslint-microsoft-contrib"],
"rulesDirectory": ["node_modules/tslint-microsoft-contrib"],
"rules": {
// ...
}
"extends": ["tslint-microsoft-contrib/configs/stable.json"]
// ...
}
```

These rules will not be added to in minor or patch releases, but will be in major releases.

#### Latest

To run with the latest and greatest rules ([configs/latest.json](./configs/latest.json)), extend from `tslint-microsoft-contrib/configs/latest`:

```json
{
"extends": ["tslint-microsoft-contrib/configs/latest.json"]
// ...
}
```

You can then disable rules you don't find useful.
These rules will not be added to in patch releases, but will be in minor releases.

#### Recommended

The "recommended" ruleset that ships by extending `tslint-microsoft-contrib` itself contains a list of rules that includes core TSLint rules.

To start, you can enable our recommended defaults ([configs/recommended.json](./configs/recommended.json)) by adding just `"tslint-microsoft-contrib"` under `"extends"` in your `tslint.json`:

```json
{
"extends": ["tslint-microsoft-contrib"]
// ...
}
```

**The "recommended" ruleset is considered legacy**; it is generally preferable to extend from the stable or latest rulesets.
We recommend you instead explicitly include `tslint:recommended`, `tslint:latest`, or `tslint:all` in your `tslint.json` rather than enable core rules through this configuration.

### Overriding Configurations

Please note, some of the default rules require the `--project` TSLint option.
You can [disable rules](https://palantir.github.io/tslint/usage/rule-flags) you don't find useful.

Also, please note that adding a rule to the recommended ruleset is considered backwards compatible.
If you rely on version ranges in your dependencies then you may find that new rules being added to the product create violations and fail your build.
We recommend you specify exact versions of lint libraries, including `tslint-microsoft-contrib`, in your `package.json`.

Expand Down
10 changes: 10 additions & 0 deletions build-tasks/common/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ const { red } = require('chalk');
const fs = require('fs');
const stripJsonComments = require('strip-json-comments');

function readDirectory(directoryName) {
try {
return fs.readdirSync(directoryName);
} catch (e) {
console.log(red(`Unable to read directory: ${directoryName}. Error code: ${e.code}`));
process.exit(1);
}
}

function readFile(fileName) {
try {
return fs.readFileSync(fileName, { encoding: 'utf8' });
Expand Down Expand Up @@ -39,6 +48,7 @@ function readJSONWithComments(fileName) {
}

module.exports = {
readDirectory,
readFile,
readJSON,
readJSONWithComments,
Expand Down
4 changes: 2 additions & 2 deletions build-tasks/common/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ const path = require('path');
const glob = require('glob');
const { readJSON } = require('./files');

function getAllRules() {
function getAllRules({ ignoreTslintRules = false } = {}) {
const contribRules = glob.sync('dist/build/*Rule.js');
const baseRules = glob.sync('node_modules/tslint/lib/rules/*Rule.js');
const baseRules = ignoreTslintRules ? [] : glob.sync('node_modules/tslint/lib/rules/*Rule.js');

return contribRules.concat(baseRules);
}
Expand Down
23 changes: 23 additions & 0 deletions build-tasks/copy-config-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Converts configs/ to ./dist/build/configs/ and configs/recommended.json to ./dist/build/recommended.json.
*/

const mkdirp = require('mkdirp');
const path = require('path');

const { readDirectory, readFile, writeFile } = require('./common/files');

const copyConfigFile = (configFileName, destinationFileName, newRulesDirectory) => {
const resolvedDestination = path.resolve(destinationFileName);
const data = readFile(path.resolve(configFileName));

writeFile(resolvedDestination, data.replace(/"rulesDirectory": \[(.*)\]/, `"rulesDirectory": ["${newRulesDirectory}"]`));
};

mkdirp.sync('./dist/build/configs');

for (const configFileName of readDirectory('./configs')) {
copyConfigFile(`./configs/${configFileName}`, `./dist/build/configs/${configFileName}`, '../');
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
}

copyConfigFile('./configs/recommended.json', './dist/build/tslint.json', './');
11 changes: 0 additions & 11 deletions build-tasks/generate-default-tslint-json.js

This file was deleted.

54 changes: 0 additions & 54 deletions build-tasks/generate-recommendations.js

This file was deleted.

54 changes: 54 additions & 0 deletions build-tasks/generate-stable-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Generates config/stable.json.
* The `recommended` metadata for each rule is added there, except if...
* - ...the rule's `metadata.group` is `'Ignored'`
* - ...the rule is also mentioned in config/latest.json (which would be a breaking change)
* - ...the recommended setting is `false` (the rule is likely deprecated)
*/

const { red } = require('chalk');
const { writeFile } = require('./common/files');
const { getAllRules, getMetadataFromFile, getMetadataValue } = require('./common/meta');

const recommendations = [];
const warnings = [];

const latestRules = new Set(Object.keys(require('../configs/latest.json').rules));

getAllRules({
ignoreTslintRules: true
}).forEach(ruleFile => {
const metadata = getMetadataFromFile(ruleFile);
const ruleName = getMetadataValue(metadata, 'ruleName');

const groupName = getMetadataValue(metadata, 'group');
if (groupName === 'Ignored') {
return;
}

let recommendation = getMetadataValue(metadata, 'recommendation', true, true);
if (recommendation === '') {
recommendation = 'true,';
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
}

// Don't mention rules recommended as disabled
if (recommendation.startsWith('false')) {
return;
}

// Don't mention rules added to the 'latest' preset, as adding them to stable.json would be a breaking change
if (latestRules.has(ruleName)) {
return;
}

recommendations.push(` "${ruleName}": ${recommendation}`);
});

if (warnings.length > 0) {
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
console.log('\n' + red(warnings.join('\n')));
process.exit(1);
}

const stableTemplate = require('./templates/stable.json.template');

writeFile('configs/stable.json', stableTemplate(recommendations));
49 changes: 0 additions & 49 deletions build-tasks/templates/recommended_ruleset.template.js

This file was deleted.

6 changes: 6 additions & 0 deletions build-tasks/templates/stable.json.template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = recommendations => `{
"rulesDirectory": ["../"],
"rules": {
${[...recommendations].sort().join('\n')}
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
}
}`;
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
Loading