为什么Sonar报告在某个班级中没有违反自定义规则?

时间:2014-12-04 13:50:50

标签: java sonarqube

我有一个自定义规则,我检查某个类是否仅用于@Repository注释类。

这是规则:

@Rule(key = QueryInNonRepositoryCheck.KEY, priority = Priority.CRITICAL, name = QueryInNonRepositoryCheck.NAME, description = QueryInNonRepositoryCheck.DESCRIPTION)
public class QueryInNonRepositoryCheck extends BaseTreeVisitor implements JavaFileScanner {

    public static final String REPOSITORY_ANNOTATION = "Repository";
    public static final String QUERY_CLASS = "Query";
    public static final String KEY = "queryInNonRepositoryCheck";
    public static final String DESCRIPTION = "be.vaph.sparta.architectuur.common.persistence.query.Query can only be used in classes annotated with @Repository.";

    public static final String MESSAGE = "Query can only be used in repository classes.";
    private static final RuleKey RULE_KEY = RuleKey.of(JavaExtensionRulesRepository.REPOSITORY_KEY, KEY);
    public static final String NAME = "Use Query only in @Repository annotated classes.";

    private JavaFileScannerContext context;

    private boolean repository;

    @Override
    public void scanFile(@Nonnull JavaFileScannerContext javaFileScannerContext) {
        this.context = javaFileScannerContext;
        scan(this.context.getTree());
    }

    @Override public void visitAnnotation(AnnotationTree annotationTree) {
        if (annotationTree.annotationType().is(Tree.Kind.IDENTIFIER)) {
            IdentifierTree identifierTree = (IdentifierTree) annotationTree.annotationType();
            if (REPOSITORY_ANNOTATION.equals(identifierTree.name())) {
                this.repository = true;
            }
        }
        super.visitAnnotation(annotationTree);
    }

    @Override
    public void visitMethodInvocation(MethodInvocationTree tree) {
        ExpressionTree expressionTree = tree.methodSelect();
        if (!this.repository) {
            if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) {
                MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree;
                ExpressionTree expression = memberSelectExpressionTree.expression();
                String query = null;
                if (expression.is(Tree.Kind.MEMBER_SELECT)) {
                    MemberSelectExpressionTree memberSelectExpressionTree1 = (MemberSelectExpressionTree) expression;
                    query = memberSelectExpressionTree1.identifier().name();
                } else if (expression.is(Tree.Kind.IDENTIFIER)) {
                    IdentifierTree identifierTree = (IdentifierTree) expression;
                    query = identifierTree.name();
                }
                if (QUERY_CLASS.equals(query)) {
                    this.context.addIssue(tree, RULE_KEY, MESSAGE);
                }
            }
        }
        super.visitMethodInvocation(tree);
    }

}

涵盖它的JUnit测试:

public class QueryInNonRepositoryCheckTest {

    @Rule
    public CheckMessagesVerifierRule checkMessagesVerifierRule = new CheckMessagesVerifierRule();

    @Test
    public void detected() throws URISyntaxException {
        // Parse a known file and use an instance of the check under test to raise the issue.
        File file = new File(getClass().getResource("/QueryInNonRepositoryTestClass.java").toURI());
        VisitorsBridge visitorsBridge = new VisitorsBridge(new QueryInNonRepositoryCheck());
        SourceFile sourceFile = JavaAstScanner.scanSingleFile(file, visitorsBridge);

        // Check the message raised by the check
        this.checkMessagesVerifierRule.verify(sourceFile.getCheckMessages())
                .next().atLine(8).withMessage(QueryInNonRepositoryCheck.MESSAGE)
                .next().atLine(13).withMessage(QueryInNonRepositoryCheck.MESSAGE)
                .next().atLine(15).withMessage(QueryInNonRepositoryCheck.MESSAGE)
                .next().atLine(17).withMessage(QueryInNonRepositoryCheck.MESSAGE)
                ;
    }

    @Test
    public void notDetected() throws URISyntaxException {
        // Parse a known file and use an instance of the check under test to raise the issue.
        File file = new File(getClass().getResource("/QueryInRepositoryTestClass.java").toURI());
        VisitorsBridge visitorsBridge = new VisitorsBridge(new QueryInNonRepositoryCheck());
        SourceFile sourceFile = JavaAstScanner.scanSingleFile(file, visitorsBridge);

        // Check the message raised by the check
        Assert.assertFalse("Geen fouten verwacht", sourceFile.hasCheckMessages());
    }

}

使用这两个测试文件:

public class QueryInNonRepositoryTestClass {

    public Object aMethod() {
        find(
                Query
                        .query(getPersistentType())
                        .eq(Rekening.PROP_HOUDER, houder)
        );

        find(Query.query(getPersistentType()).eq(Rekening.PROP_HOUDER, houder));

        be.vaph.sparta.architectuur.common.persistence.query.Query.criteria(Individu.class);

        return Query.hql("from Individu");
    }
}

@Repository("aRepository")
public class QueryInRepositoryTestClass {

    public Object aMethod() {
        find(
                Query
                        .query(getPersistentType())
                        .eq(Rekening.PROP_HOUDER, houder)
        );

        find(Query.query(getPersistentType()).eq(Rekening.PROP_HOUDER, houder));

        be.vaph.sparta.architectuur.common.persistence.query.Query.criteria(Individu.class);

        return Query.hql("from Individu");
    }
}

在Sonar构建之后,它会报告15个规则违规。在调查这些违规行为是有效的。但是,有一个有2个故意违反规则的课程标记为此类。

@Service("rekeningService")
public class RekeningServiceImpl implements RekeningService {

    [...]

    public void sonarCheckTest() {
        this.rekeningRepository.find(
                Query.query(Rekening.class) // should be a violation but not detected
        );
        this.rekeningRepository.find(Query.query(Rekening.class)); // should be a violation but not detected
        Logger.getLogger("DON'T DO THIS"); // other custom rule violation, correctly detected 
    }
}

我们有其他自定义规则,例如。一个在使用Logger时发出警告的,并且正确触发了这些警告。

知道可能导致这种情况的原因吗?

0 个答案:

没有答案