From b6e7174f623d1197fd8f7a857aa1fb4a621615ae Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 13 Feb 2018 16:51:57 +0100 Subject: [PATCH] build: add tslint rule to enforce deletion targets (#9881) Adds a tslint rule that will mark any deletion targets that are due to be deleted. --- tools/tslint-rules/deletionTargetRule.ts | 61 ++++++++++++++++++++++++ tslint.json | 1 + 2 files changed, 62 insertions(+) create mode 100644 tools/tslint-rules/deletionTargetRule.ts diff --git a/tools/tslint-rules/deletionTargetRule.ts b/tools/tslint-rules/deletionTargetRule.ts new file mode 100644 index 00000000000..25b9d0dd50f --- /dev/null +++ b/tools/tslint-rules/deletionTargetRule.ts @@ -0,0 +1,61 @@ +import * as ts from 'typescript'; +import * as Lint from 'tslint'; +import * as utils from 'tsutils'; +import * as path from 'path'; + +/** + * Rule ensuring that deletion targets have not expired. + * The current version is taken from the `package.json`. + */ +export class Rule extends Lint.Rules.AbstractRule { + apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const packageVersion = require(path.join(process.cwd(), 'package.json')).version; + + return this.applyWithFunction(sourceFile, (ctx: Lint.WalkContext) => { + utils.forEachComment(ctx.sourceFile, (file, {pos, end}) => { + const commentText = file.substring(pos, end); + + if (commentText.indexOf('@deletion-target') === -1) { + return; + } + + const version = commentText.match(/\d+\.\d+\.\d+/); + + if (!version) { + ctx.addFailure(pos, end, '@deletion-target must have a version.'); + } else if (this._hasExpired(packageVersion, version[0])) { + ctx.addFailure(pos, end, `Deletion target at ${version[0]} is due to be deleted. ` + + `Current version is ${packageVersion}.`); + } + }); + }); + } + + /** + * Checks whether a version has expired, based on the current version. + * @param currentVersion Current version of the package. + * @param deletionTarget Version that is being checked. + */ + private _hasExpired(currentVersion: string, deletionTarget: string) { + if (currentVersion === deletionTarget) { + return true; + } + + const current = this._parseVersion(currentVersion); + const target = this._parseVersion(deletionTarget); + + return target.major < current.major || + (target.major === current.major && target.minor < current.minor) || + ( + target.major === current.major && + target.minor === current.minor && + target.patch < current.patch + ); + } + + /** Converts a version string into an object. */ + private _parseVersion(version: string) { + const [major = 0, minor = 0, patch = 0] = version.split('.').map(segment => parseInt(segment)); + return {major, minor, patch}; + } +} diff --git a/tslint.json b/tslint.json index 1621579d937..f060771a173 100644 --- a/tslint.json +++ b/tslint.json @@ -120,6 +120,7 @@ "./tools/package-tools/rollup-globals.ts", "src/+(lib|cdk|material-examples|material-experimental|cdk-experimental)/**/*.ts" ], + "deletion-target": true, "no-unescaped-html-tag": true } }