Skip to content

Commit

Permalink
Add TodoComment check
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenLooman committed Jan 2, 2024
1 parent bf017f6 commit b6bc4ae
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Add DefinitionKeeperTypeKeeperAdapter for compatibility with previous type system.
- Show inlayhints for ATOM nodes, as a configurable option.
- Refactor LocalTypeReasoner state to own class.
- Add TodoComment check.

0.8.3 (unreleased)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import nl.ramsolutions.sw.magik.checks.checks.SizeZeroEmptyCheck;
import nl.ramsolutions.sw.magik.checks.checks.SwMethodDocCheck;
import nl.ramsolutions.sw.magik.checks.checks.SyntaxErrorCheck;
import nl.ramsolutions.sw.magik.checks.checks.TodoCommentCheck;
import nl.ramsolutions.sw.magik.checks.checks.TrailingWhitespaceCheck;
import nl.ramsolutions.sw.magik.checks.checks.TypeDocCheck;
import nl.ramsolutions.sw.magik.checks.checks.UndefinedVariableCheck;
Expand Down Expand Up @@ -86,6 +87,7 @@ public static List<Class<?>> getChecks() {
SizeZeroEmptyCheck.class,
SwMethodDocCheck.class,
SyntaxErrorCheck.class,
TodoCommentCheck.class,
TrailingWhitespaceCheck.class,
TypeDocCheck.class,
UndefinedVariableCheck.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package nl.ramsolutions.sw.magik.checks.checks;

import com.sonar.sslr.api.Token;
import com.sonar.sslr.api.Trivia;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import nl.ramsolutions.sw.magik.checks.MagikCheck;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;

/**
* Todo/Fixme/... comment check.
*/
@Rule(key = TodoCommentCheck.CHECK_KEY)
public class TodoCommentCheck extends MagikCheck {

@SuppressWarnings("checkstyle:JavadocVariable")
public static final String CHECK_KEY = "CommentTodo";
private static final String MESSAGE = "Todo comment: %s.";

private static final String DEFAULT_FORBIDDEN_WORDS = "TODO,FIXME,HACK,XXX";

/**
* List of comment words, separated by ','.
*/
@RuleProperty(
key = "forbidden comment words",
defaultValue = "" + DEFAULT_FORBIDDEN_WORDS,
description = "List of forbidden words, separated by ',', case sensitive",
type = "STRING")
@SuppressWarnings("checkstyle:VisibilityModifier")
public String forbiddenWords = DEFAULT_FORBIDDEN_WORDS;

private Collection<String> getForbiddenWords() {
return Arrays.stream(this.forbiddenWords.split(","))
.map(String::trim)
.collect(Collectors.toSet());
}

@Override
protected void walkTrivia(final Trivia trivia) {
if (!trivia.isComment()) {
return;
}

trivia.getTokens().forEach(this::checkComment);
}

private void checkComment(final Token token) {
final String comment = token.getOriginalValue();
this.getForbiddenWords().stream()
.forEach(word -> {
int fromIndex = 0;
while (fromIndex != -1) {
fromIndex = comment.indexOf(word, fromIndex);
if (fromIndex == -1) {
break;
}

final String message = String.format(MESSAGE, word);
this.addIssue(token.getLine(), fromIndex, token.getLine(), fromIndex + word.length(), message);

fromIndex += word.length();
}
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>XXX/TODO/FIXME comments should be resolved.</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "TODO comment",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "15min"
},
"tags": [
"convention"
],
"defaultSeverity": "Minor",
"ruleSpecification": "CommentTodo",
"sqKey": "comment-todo"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package nl.ramsolutions.sw.magik.checks.checks;

import java.util.List;
import nl.ramsolutions.sw.magik.checks.MagikCheck;
import nl.ramsolutions.sw.magik.checks.MagikIssue;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Test {@link TodoCommentCheck}.
*/
class TodoCommentCheckTest extends MagikCheckTestBase {

@ParameterizedTest
@ValueSource(strings = {
"# This should not trigger an issue",
"# This should trigger an issue, although it is used as a hack."
})
void testOk(final String code) {
final MagikCheck check = new TodoCommentCheck();
final List<MagikIssue> issues = this.runCheck(code, check);
assertThat(issues).isEmpty();
}

@ParameterizedTest
@ValueSource(strings = {
"# TODO: This should trigger an issue",
"# XXX: This should trigger an issue"
})
void testForbiddenWord(final String code) {
final MagikCheck check = new TodoCommentCheck();
final List<MagikIssue> issues = this.runCheck(code, check);
assertThat(issues).hasSize(1);
}

@ParameterizedTest
@ValueSource(strings = {
"# XXX TODO: This should trigger two issues",
"# XXX FIXME: This should trigger two issues"
})
void testForbiddenWordTwice(final String code) {
final MagikCheck check = new TodoCommentCheck();
final List<MagikIssue> issues = this.runCheck(code, check);
assertThat(issues).hasSize(2);
}

}

0 comments on commit b6bc4ae

Please sign in to comment.