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

New rule: no-useless-files #349

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The tslint.json file does not change format when using this package. Just add ou

##### Which Rules Should I Turn On?
There certainly are a lot of options! Here are some links to get you started.
* Easiest Option - Our recommended ruleset is here: [recommended_ruleset.js](recommended_ruleset.js). You can also easily extend the ruleset by adding `"extends": "tslint-microsoft-contrib"` to your configuration. Please note, the default rules require the `--type-check` and `--project` TSLint options.
* Easiest Option - Our recommended ruleset is here: [recommended_ruleset.js](recommended_ruleset.js). You can also easily extend the ruleset by adding `"extends": "tslint-microsoft-contrib"` to your configuration. Please note, the default rules require the `--type-check` and `--project` TSLint options.
* A nice blog post on the MSDN secure development blog can be found here: [Automating Secure Development Lifecycle Checks in TypeScript with TSLint](https://blogs.msdn.microsoft.com/secdevblog/2016/05/11/automating-secure-development-lifecycle-checks-in-typescript-with-tslint/)
* A wiki briefly describing the SDL and related rules is here: [TSLint and the Microsoft Security Development Lifecycle](https://github.com/Microsoft/tslint-microsoft-contrib/wiki/TSLint-and-the-Microsoft-Security-Development-Lifecycle)
* And our configuration file with all options is available here: [tslint.json](tslint.json)
Expand Down Expand Up @@ -129,6 +129,7 @@ Rule Name | Description | Since
`no-unnecessary-semicolons` | Remove unnecessary semicolons | 0.0.1
`no-unsupported-browser-code` | Avoid writing browser-specific code for unsupported browser versions. Browser versions are specified in the rule configuration options, eg: `[true, [ "IE 11", "Firefox > 40", "Chrome >= 45" ] ]`. Browser-specific blocks of code can then be designated with a single-line comment, like so: `// Browser specific: IE 10`, or with a jsdoc like this: `@browserspecific chrome 40`. | 2.0.10
`no-unused-imports` | Deprecated - This rule is now covered by TSLint's no-unused-variables rule. However, it can still be useful to enable this rule and pair it with the fix-no-unused-imports formatter. | 0.0.1
`no-useless-files` | Avoid keeping files around that only contain commented out code, are completely empty, or only contain whitespace characters | 4.0.2
`no-var-self` | Do not use `var self = this`; instead, manage scope with arrow functions/lambdas. Self variables are a common practice in JavaScript but can be avoided in TypeScript. By default the rule bans any assignments of the `this` reference. If you want to enforce a naming convention or allow some usages then configure the rule with a regex. By default the rule is configured with `(?!)` which matches nothing. You can pass `^self$` to allow variables named self or pass `^(?!self$)` to allow anything other than self, for example| 2.0.8
`no-with-statement` | Do not use with statements. Assign the item to a new variable instead | 0.0.1
`non-literal-require` | Detect `require()` function calls for something that is not a string literal. For security reasons, it is best to only require() string literals. Otherwise, it is perhaps possible for an attacker to somehow change the value and download arbitrary Javascript into your page. | 2.0.14
Expand Down
1 change: 1 addition & 0 deletions recommended_ruleset.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ module.exports = {
"no-unnecessary-local-variable": true,
"no-unnecessary-qualifier": true,
"no-unsupported-browser-code": true,
"no-useless-files": true,
"no-var-keyword": true,
"no-var-requires": true,
"no-var-self": true,
Expand Down
44 changes: 44 additions & 0 deletions src/noUselessFilesRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as ts from 'typescript';
import * as Lint from 'tslint';

import {ExtendedMetadata} from './utils/ExtendedMetadata';

const FAILURE_STRING_EMPTY: string = 'This file is empty and should be deleted.';
const FAILURE_STRING_COMMENTS: string = 'This file only contains comments and should be deleted.';

/**
* Implementation of the no-useless-files rule.
*/
export class Rule extends Lint.Rules.AbstractRule {

public static metadata: ExtendedMetadata = {
ruleName: 'no-useless-files',
type: 'maintainability',
description: 'Locates files that only contain commented out code, whitespace characters, or have no content',
options: null,
optionsDescription: '',
typescriptOnly: false,
issueClass: 'Non-SDL',
issueType: 'Warning',
severity: 'Low',
level: 'Opportunity for Excellence',
group: 'Clarity',
commonWeaknessEnumeration: '398' //Indicator of Poor Code Quality
};

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const ruleFailures: Lint.RuleFailure[] = [];

const fileContent = sourceFile.getFullText().trim();
const fileContentNoComments = sourceFile.getText().trim();

if (fileContent.length === 0) {
//This file only contains whitespace characters, a totally empty & useless file
ruleFailures.push(new Lint.RuleFailure(sourceFile, 0, 0, FAILURE_STRING_EMPTY, this.getOptions().ruleName));
} else if (fileContentNoComments.length === 0) {
//This file only contains code comments, not empty but completely useless
ruleFailures.push(new Lint.RuleFailure(sourceFile, 0, 0, FAILURE_STRING_COMMENTS, this.getOptions().ruleName));
}
return ruleFailures;
}
}
75 changes: 75 additions & 0 deletions src/tests/NoUselessFilesRuleTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {TestHelper} from './TestHelper';

/**
* Unit tests.
*/
describe('noUselessFilesRule', () : void => {

const ruleName : string = 'no-useless-files';

it('should pass on a normal file that contains code', () : void => {
const script : string = `
export class MyClass {
constructor () {
console.log("foo");
}
}`;

TestHelper.assertViolations(ruleName, script, [ ]);
});

it('should fail on a file that only contains single-line comments', () : void => {
const script : string = `// This is the only comment in this file`;

TestHelper.assertViolations(ruleName, script, [{
'failure': 'This file only contains comments and should be deleted.',
'name': 'file.ts',
'ruleName': ruleName,
'startPosition': { 'character': 1, 'line': 1 }
}]);
});

it('should fail on a file that only contains multi-line comments', () : void => {
const script : string = `/*
export class MyClass {
constructor () {
console.log("foo");
}
}
*/`;

TestHelper.assertViolations(ruleName, script, [{
'failure': 'This file only contains comments and should be deleted.',
'name': 'file.ts',
'ruleName': ruleName,
'startPosition': { 'character': 1, 'line': 1 }
}]);
});

it('should fail on a file that only contains whitespace', () : void => {
//The below string contains spaces, tabs, and linebreaks
const script : string = `


`;

TestHelper.assertViolations(ruleName, script, [{
'failure': 'This file is empty and should be deleted.',
'name': 'file.ts',
'ruleName': ruleName,
'startPosition': { 'character': 1, 'line': 1 }
}]);
});

it('should fail on a file that has no content', () : void => {
const script : string = ``;

TestHelper.assertViolations(ruleName, script, [{
'failure': 'This file is empty and should be deleted.',
'name': 'file.ts',
'ruleName': ruleName,
'startPosition': { 'character': 1, 'line': 1 }
}]);
});

});
1 change: 1 addition & 0 deletions tslint-warnings.csv
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ CWE 710 - Coding Standards Violation"
no-use-before-declare,Disallows usage of variables before their declaration.,TSLINTUU9UNF,tslint,Non-SDL,Error,Critical,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,"398, 456, 710","CWE 398 - Indicator of Poor Code Quality
CWE 456 - Missing Initialization of a Variable
CWE 710 - Coding Standards Violation"
no-useless-files,"Locates files that only contain commented out code, whitespace characters, or have no content",TSLINTGOUON3,tslint,Non-SDL,Warning,Low,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,398,"CWE 398 - Indicator of Poor Code Quality"
no-var-keyword,Disallows usage of the `var` keyword.,TSLINT15BQNA,tslint,Non-SDL,Warning,Important,Opportunity for Excellence,See description on the tslint or tslint-microsoft-contrib website,TSLint Procedure,"398, 705, 710","CWE 398 - Indicator of Poor Code Quality
CWE 705 - Incorrect Control Flow Scoping
CWE 710 - Coding Standards Violation"
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@
"check-operator",
"check-separator",
"check-type"
]
],
"no-useless-files": true
}
}