diff --git a/build-config.js b/build-config.js index c8beef05fdd..26b3f8199bc 100644 --- a/build-config.js +++ b/build-config.js @@ -9,10 +9,12 @@ const buildVersion = require('./package.json').version; /** License that will be placed inside of all created bundles. */ const buildLicense = `/** - * @license Angular Material v${buildVersion} - * Copyright (c) 2017 Google, Inc. https://material.angular.io/ - * License: MIT - */`; + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */`; module.exports = { projectVersion: buildVersion, diff --git a/tools/tslint-rules/requireLicenseBannerRule.js b/tools/tslint-rules/requireLicenseBannerRule.js new file mode 100644 index 00000000000..4f710e88905 --- /dev/null +++ b/tools/tslint-rules/requireLicenseBannerRule.js @@ -0,0 +1,56 @@ +const Lint = require('tslint'); +const path = require('path'); +const buildConfig = require('../../build-config'); + +/** Paths to the directories that are public packages and should be validated. */ +const packageDirs = [ + path.join(buildConfig.packagesDir, 'lib'), + path.join(buildConfig.packagesDir, 'cdk') +]; + +/** License banner that is placed at the top of every public TypeScript file. */ +const licenseBanner = buildConfig.licenseBanner; + +/** Failure message that will be shown if a license banner is missing. */ +const ERROR_MESSAGE = 'Missing license header in this TypeScript file. ' + + 'Every TypeScript file of the library needs to have the Google license banner at the top.'; + +/** TSLint fix that can be used to add the license banner easily. */ +const tslintFix = Lint.Replacement.appendText(0, licenseBanner + '\n\n'); + +/** + * Rule that walks through all TypeScript files of public packages and shows failures if a + * file does not have the license banner at the top of the file. + */ +class Rule extends Lint.Rules.AbstractRule { + + apply(sourceFile) { + return this.applyWithWalker(new RequireLicenseBannerWalker(sourceFile, this.getOptions())); + } +} + +class RequireLicenseBannerWalker extends Lint.RuleWalker { + + visitSourceFile(sourceFile) { + const filePath = path.join(buildConfig.projectDir, sourceFile.fileName); + + // Do not check TypeScript source files that are not inside of a public package. + if (!packageDirs.some(packageDir => filePath.includes(packageDir))) { + return; + } + + // Do not check source files inside of public packages that are spec or definition files. + if (filePath.endsWith('.spec.ts') || filePath.endsWith('.d.ts')) { + return; + } + + const fileContent = sourceFile.getFullText(); + const licenseCommentPos = fileContent.indexOf(licenseBanner); + + if (licenseCommentPos !== 0) { + return this.addFailureAt(0, 0, ERROR_MESSAGE, tslintFix); + } + } +} + +exports.Rule = Rule; diff --git a/tslint.json b/tslint.json index e8ec1dd2984..ec9c7ecc83d 100644 --- a/tslint.json +++ b/tslint.json @@ -72,6 +72,7 @@ // Disallows importing the whole RxJS library. Submodules can be still imported. "import-blacklist": [true, "rxjs"], // Avoids inconsistent linebreak styles in source files. Forces developers to use LF linebreaks. - "linebreak-style": [true, "LF"] + "linebreak-style": [true, "LF"], + "require-license-banner": true } }