Skip to content

Commit

Permalink
Added comment format rule
Browse files Browse the repository at this point in the history
  • Loading branch information
gscshoyru committed Dec 5, 2013
1 parent 9c16e16 commit b85c254
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 1 deletion.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ Supported Rules
-----

* `class-name` enforces PascalCased class and interface names.
* `comment-format` enforces rules for single-line comments. Rule options:
* `"check-space"` enforces the rule that all single-line comments must begin with a space, as in `// comment`
* `"check-lowercase"` enforces the rule that the first non-whitespace character of a comment must be lowercase, if applicable
* `curly` enforces braces for `if`/`for`/`do`/`while` statements.
* `eofline` enforces the file to end with a newline.
* `forin` enforces a `for ... in` statement to be filtered with an `if` statement.*
* `indent` enforces consistent indentation levels (currently disabled).
* `interface-name` enforces the rule that interface names must begin with a capital 'I'
* `interface-name` enforces the rule that interface names must begin with a capital 'I'
* `label-position` enforces labels only on sensible statements.
* `label-undefined` checks that labels are defined before usage.
* `max-line-length` sets the maximum length of a line.
Expand Down
87 changes: 87 additions & 0 deletions src/rules/commentFormatRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2013 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/// <reference path='../../lib/tslint.d.ts' />

var OPTION_SPACE = "check-space";
var OPTION_LOWERCASE = "check-lowercase";

export class Rule extends Lint.Rules.AbstractRule {
static LOWERCASE_FAILURE = "comment must start with lowercase letter";
static LEADING_SPACE_FAILURE = "comment must start with a space";

public apply(syntaxTree: TypeScript.SyntaxTree): Lint.RuleFailure[] {
return this.applyWithWalker(new CommentWalker(syntaxTree, this.getOptions()));
}
}

class CommentWalker extends Lint.RuleWalker {
public visitToken(token: TypeScript.ISyntaxToken): void {
this.findFailuresForTrivia(token.leadingTrivia().toArray(), this.position());
this.findFailuresForTrivia(token.trailingTrivia().toArray(), this.position() + token.leadingTriviaWidth() + token.width());

super.visitToken(token);
}

private findFailuresForTrivia(triviaList: TypeScript.ISyntaxTrivia[], startingPosition: number) {
var currentPosition = startingPosition;
triviaList.forEach((triviaItem) => {
if (triviaItem.kind() === TypeScript.SyntaxKind.SingleLineCommentTrivia) {
var commentText = triviaItem.fullText();
if (this.hasOption(OPTION_SPACE)) {
if (!this.startsWithSpace(commentText)) {
var leadingSpaceFailure = this.createFailure(currentPosition, triviaItem.fullWidth(), Rule.LEADING_SPACE_FAILURE);
this.addFailure(leadingSpaceFailure);
}
}
if (this.hasOption(OPTION_LOWERCASE)) {
if (!this.startsWithLowercase(commentText)) {
var lowercaseFailure = this.createFailure(currentPosition, triviaItem.fullWidth(), Rule.LOWERCASE_FAILURE);
this.addFailure(lowercaseFailure);
}
}
}
currentPosition += triviaItem.fullWidth();
});
}

private startsWithSpace(commentText: string): boolean {
if (commentText.length <= 2) {
return true; // comment is "//"? Technically not a violation.
}

var firstCharacter = commentText.charAt(2); // first character after the space
return firstCharacter === " ";
}

private startsWithLowercase(commentText: string): boolean {
if (commentText.length <= 2) {
return true; // comment is "//"? Technically not a violation.
}

// regex is "start of string"//"any amount of whitespace"("word character")
var firstCharacterMatch = commentText.match(/^\/\/\s*(\w)/);
if (firstCharacterMatch != null) {
// the first group matched, i.e. the thing in the parens, is the first non-space character, if it's alphanumeric
var firstCharacter = firstCharacterMatch[1];
return firstCharacter === firstCharacter.toLowerCase();
} else {
// first character isn't alphanumeric/doesn't exist? Technically not a violation
return true;
}
}

}
9 changes: 9 additions & 0 deletions test/files/rules/comment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Clazz { // this comment is correct
/* block comment
* adada
*/
public funcxion() { // This comment has a capital letter starting it
//This comment is on its own line, and starts with a capital _and_ no space
console.log("test"); //this comment has no space
}
}
42 changes: 42 additions & 0 deletions test/rules/commentFormatRuleTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2013 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/// <reference path='../references.ts' />

describe("<comment-format>", () => {
var CommentFormatRule = Lint.Test.getRule("comment-format");

it("ensures comments start with a space and a lowercase letter", () => {
var fileName = "rules/comment.test.ts";
var createLowercaseFailure = Lint.Test.createFailuresOnFile(fileName, CommentFormatRule.LOWERCASE_FAILURE);
var createLeadingSpaceFailure = Lint.Test.createFailuresOnFile(fileName, CommentFormatRule.LEADING_SPACE_FAILURE);
var expectedFailure1 = createLowercaseFailure([5, 25], [5, 73]);
var expectedFailure2 = createLowercaseFailure([6, 9], [6, 84]);
var expectedFailure3 = createLeadingSpaceFailure([6, 9], [6, 84]);
var expectedFailure4 = createLeadingSpaceFailure([7, 30], [7, 57]);

var options = [true,
"check-space",
"check-lowercase"
];
var actualFailures = Lint.Test.applyRuleOnFile(fileName, CommentFormatRule, options);

Lint.Test.assertContainsFailure(actualFailures, expectedFailure1);
Lint.Test.assertContainsFailure(actualFailures, expectedFailure2);
Lint.Test.assertContainsFailure(actualFailures, expectedFailure3);
Lint.Test.assertContainsFailure(actualFailures, expectedFailure4);
});
});

0 comments on commit b85c254

Please sign in to comment.