From 9f8394b46a01f7ddac672afddd546ed6e82ccd7e Mon Sep 17 00:00:00 2001 From: Godin Date: Tue, 23 Nov 2010 18:52:32 +0000 Subject: SONAR-1845, SONAR-1931: Create a new Squid rules to check class and method complexity --- .../sonar/java/ast/check/ClassComplexityCheck.java | 75 ---------------------- .../java/ast/check/MethodComplexityCheck.java | 44 ------------- .../org/sonar/java/bytecode/check/DITCheck.java | 40 ------------ .../java/org/sonar/java/squid/SquidScanner.java | 48 ++++++++++++++ .../org/sonar/java/squid/SquidVisitorNotifier.java | 47 ++++++++++++++ .../java/squid/check/ClassComplexityCheck.java | 51 +++++++++++++++ .../java/org/sonar/java/squid/check/DITCheck.java | 38 +++++++++++ .../java/squid/check/MethodComplexityCheck.java | 31 +++++++++ .../org/sonar/java/squid/check/SquidCheck.java | 12 ++++ .../org/sonar/java/squid/visitor/SquidVisitor.java | 28 ++++++++ .../org/sonar/plugins/squid/SquidExecutor.java | 22 +++++-- .../sonar/plugins/squid/SquidRuleRepository.java | 12 ++-- .../java/ast/check/ClassComplexityCheckTest.java | 64 ------------------ .../java/ast/check/MethodComplexityCheckTest.java | 35 ---------- .../sonar/java/bytecode/check/DITCheckTest.java | 44 ------------- .../java/squid/check/ClassComplexityCheckTest.java | 68 ++++++++++++++++++++ .../org/sonar/java/squid/check/DITCheckTest.java | 46 +++++++++++++ .../squid/check/MethodComplexityCheckTest.java | 39 +++++++++++ 18 files changed, 431 insertions(+), 313 deletions(-) delete mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/ClassComplexityCheck.java delete mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/MethodComplexityCheck.java delete mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/bytecode/check/DITCheck.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidScanner.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidVisitorNotifier.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/ClassComplexityCheck.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/DITCheck.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/MethodComplexityCheck.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/SquidCheck.java create mode 100644 plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/visitor/SquidVisitor.java delete mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/ClassComplexityCheckTest.java delete mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/MethodComplexityCheckTest.java delete mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/bytecode/check/DITCheckTest.java create mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/ClassComplexityCheckTest.java create mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/DITCheckTest.java create mode 100644 plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/MethodComplexityCheckTest.java (limited to 'plugins') diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/ClassComplexityCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/ClassComplexityCheck.java deleted file mode 100644 index 4a724126561..00000000000 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/ClassComplexityCheck.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2009 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ - -package org.sonar.java.ast.check; - -import org.sonar.check.IsoCategory; -import org.sonar.check.Rule; -import org.sonar.check.RuleProperty; -import org.sonar.java.ast.visitor.ClassVisitor; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceCode; -import org.sonar.squid.api.SourceFile; -import org.sonar.squid.measures.Metric; - -import com.puppycrawl.tools.checkstyle.api.DetailAST; - -import java.util.List; - -@Rule(key = "ClassComplexityCheck", name = "ClassComplexityCheck", isoCategory = IsoCategory.Maintainability) -public class ClassComplexityCheck extends JavaAstCheck { - - @RuleProperty(description = "Threshold.") - private Integer threshold; - - @Override - public List getWantedTokens() { - return ClassVisitor.wantedTokens; - } - - @Override - public void leaveToken(DetailAST ast) { - SourceCode currentResource = peekSourceCode(); - int complexity = calculateComplexity(currentResource); - if (complexity > threshold) { - CheckMessage message = new CheckMessage(this, "Class complexity exceeds " + threshold + "."); - message.setLine(ast.getLineNo()); - message.setCost(complexity - threshold); - SourceFile sourceFile = currentResource.getParent(SourceFile.class); - sourceFile.log(message); - } - } - - private int calculateComplexity(SourceCode sourceCode) { - int result = 0; - if (sourceCode.getChildren() != null) { - for (SourceCode child : sourceCode.getChildren()) { - result += calculateComplexity(child); - } - } - result += sourceCode.getInt(Metric.COMPLEXITY); - return result; - } - - public void setThreshold(int threshold) { - this.threshold = threshold; - } - -} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/MethodComplexityCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/MethodComplexityCheck.java deleted file mode 100644 index 425c1dc6d59..00000000000 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/ast/check/MethodComplexityCheck.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sonar.java.ast.check; - -import org.sonar.check.IsoCategory; -import org.sonar.check.Rule; -import org.sonar.check.RuleProperty; -import org.sonar.java.ast.visitor.MethodVisitor; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceCode; -import org.sonar.squid.api.SourceFile; -import org.sonar.squid.measures.Metric; - -import com.puppycrawl.tools.checkstyle.api.DetailAST; - -import java.util.List; - -@Rule(key = "MethodComplexityCheck", name = "MethodComplexityCheck", isoCategory = IsoCategory.Maintainability) -public class MethodComplexityCheck extends JavaAstCheck { - - @RuleProperty(description = "Threshold.") - private Integer threshold; - - @Override - public List getWantedTokens() { - return MethodVisitor.wantedTokens; - } - - @Override - public void leaveToken(DetailAST ast) { - SourceCode currentResource = peekSourceCode(); - int complexity = currentResource.getInt(Metric.COMPLEXITY) + currentResource.getInt(Metric.BRANCHES) + 1; - if (complexity > threshold) { - CheckMessage message = new CheckMessage(this, "Method complexity exceeds " + threshold + "."); - message.setLine(ast.getLineNo()); - message.setCost(complexity - threshold); - SourceFile sourceFile = currentResource.getParent(SourceFile.class); - sourceFile.log(message); - } - } - - public void setThreshold(int threshold) { - this.threshold = threshold; - } - -} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/bytecode/check/DITCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/bytecode/check/DITCheck.java deleted file mode 100644 index 0b88ee55da1..00000000000 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/bytecode/check/DITCheck.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.sonar.java.bytecode.check; - -import org.sonar.check.IsoCategory; -import org.sonar.check.Priority; -import org.sonar.check.Rule; -import org.sonar.check.RuleProperty; -import org.sonar.java.bytecode.asm.AsmClass; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceClass; -import org.sonar.squid.measures.Metric; - -@Rule(key = "MaximumInheritanceDepth", name = "Avoid too deep inheritance tree", isoCategory = IsoCategory.Maintainability, - priority = Priority.MAJOR, description = "

Inheritance is certainly one of the most valuable concept of object-oriented " - + "programming. It's a way to compartmentalize and reuse code by creating collections of attributes and behaviors called " - + "classes which can be based on previously created classes. But abusing of this concept by creating a deep inheritance tree " - + "can lead to very complex and unmaintainable source code.

" - + "

Most of the time a too deep inheritance tree is due to bad object oriented design which has led to systematically use " - + "'inheritance' when 'composition' would suit better.

") -public class DITCheck extends BytecodeCheck { - - @RuleProperty(description = "Maximum depth of the inheritance tree.", defaultValue = "5") - private Integer max; - - @Override - public void visitClass(AsmClass asmClass) { - SourceClass sourceClass = getSourceClass(asmClass); - int dit = sourceClass.getInt(Metric.DIT); - if (dit > max) { - CheckMessage message = new CheckMessage(this, "This class has " + dit - + " parents which makes it complex to understand and to maintain."); - message.setLine(sourceClass.getStartAtLine()); - message.setCost(dit - max); - getSourceFile(asmClass).log(message); - } - } - - public void setMax(int max) { - this.max = max; - } -} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidScanner.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidScanner.java new file mode 100644 index 00000000000..deb6535ff27 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidScanner.java @@ -0,0 +1,48 @@ +package org.sonar.java.squid; + +import java.util.Collection; +import java.util.Collections; + +import org.sonar.java.squid.check.SquidCheck; +import org.sonar.java.squid.visitor.SquidVisitor; +import org.sonar.squid.api.CodeScanner; +import org.sonar.squid.api.CodeVisitor; +import org.sonar.squid.api.SourceClass; +import org.sonar.squid.api.SourceCode; +import org.sonar.squid.indexer.QueryByType; +import org.sonar.squid.indexer.SquidIndex; + +public class SquidScanner extends CodeScanner { + + private SquidIndex indexer; + + public SquidScanner(SquidIndex indexer) { + this.indexer = indexer; + } + + public void scan() { + Collection classes = indexer.search(new QueryByType(SourceClass.class)); + notifySquidVisitors(classes); + } + + private void notifySquidVisitors(Collection classes) { + SquidVisitor[] visitorArray = getVisitors().toArray(new SquidVisitor[getVisitors().size()]); + for (SourceCode sourceClass : classes) { + SquidVisitorNotifier visitorNotifier = new SquidVisitorNotifier((SourceClass) sourceClass, visitorArray); + visitorNotifier.notifyVisitors(indexer); + } + } + + @Override + public Collection> getVisitorClasses() { + return Collections.emptyList(); + } + + @Override + public void accept(CodeVisitor visitor) { + if (visitor instanceof SquidCheck) { + super.accept(visitor); + } + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidVisitorNotifier.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidVisitorNotifier.java new file mode 100644 index 00000000000..740db3c7a7d --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/SquidVisitorNotifier.java @@ -0,0 +1,47 @@ +package org.sonar.java.squid; + +import org.sonar.java.squid.visitor.SquidVisitor; +import org.sonar.squid.api.SourceClass; +import org.sonar.squid.api.SourceCode; +import org.sonar.squid.api.SourceMethod; +import org.sonar.squid.indexer.SquidIndex; + +public class SquidVisitorNotifier { + + private final SourceClass sourceClass; + private final SquidVisitor[] squidVisitors; + + public SquidVisitorNotifier(SourceClass sourceClass, SquidVisitor[] squidVisitors) { + this.sourceClass = sourceClass; + this.squidVisitors = new SquidVisitor[squidVisitors.length]; + System.arraycopy(squidVisitors, 0, this.squidVisitors, 0, squidVisitors.length); + } + + public void notifyVisitors(SquidIndex indexer) { + for (SquidVisitor visitor : squidVisitors) { + visitor.setSquidIndex(indexer); + } + callVisitClass(); + callVisitMethod(); + } + + private void callVisitClass() { + for (SquidVisitor visitor : squidVisitors) { + visitor.visitClass(sourceClass); + } + } + + private void callVisitMethod() { + if (sourceClass.getChildren() == null) { // TODO Most probably SourceCode#hasChildren() shouldn't be protected + return; + } + for (SourceCode sourceCode : sourceClass.getChildren()) { + if (sourceCode instanceof SourceMethod) { + SourceMethod sourceMethod = (SourceMethod) sourceCode; + for (SquidVisitor visitor : squidVisitors) { + visitor.visitMethod(sourceMethod); + } + } + } + } +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/ClassComplexityCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/ClassComplexityCheck.java new file mode 100644 index 00000000000..c529996cd19 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/ClassComplexityCheck.java @@ -0,0 +1,51 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +package org.sonar.java.squid.check; + +import org.sonar.check.IsoCategory; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceClass; +import org.sonar.squid.measures.Metric; + +@Rule(key = "ClassComplexityCheck", name = "ClassComplexityCheck", isoCategory = IsoCategory.Maintainability) +public class ClassComplexityCheck extends SquidCheck { + + @RuleProperty(description = "Threshold.") + private Integer threshold; + + @Override + public void visitClass(SourceClass sourceClass) { + int complexity = sourceClass.getInt(Metric.COMPLEXITY); + if (complexity > threshold) { + CheckMessage message = new CheckMessage(this, "Class complexity exceeds " + threshold + "."); + message.setLine(sourceClass.getStartAtLine()); + message.setCost(complexity - threshold); + getSourceFile(sourceClass).log(message); + } + } + + public void setThreshold(int threshold) { + this.threshold = threshold; + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/DITCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/DITCheck.java new file mode 100644 index 00000000000..d202f591ab1 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/DITCheck.java @@ -0,0 +1,38 @@ +package org.sonar.java.squid.check; + +import org.sonar.check.IsoCategory; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceClass; +import org.sonar.squid.measures.Metric; + +@Rule(key = "MaximumInheritanceDepth", name = "Avoid too deep inheritance tree", isoCategory = IsoCategory.Maintainability, + priority = Priority.MAJOR, description = "

Inheritance is certainly one of the most valuable concept of object-oriented " + + "programming. It's a way to compartmentalize and reuse code by creating collections of attributes and behaviors called " + + "classes which can be based on previously created classes. But abusing of this concept by creating a deep inheritance tree " + + "can lead to very complex and unmaintainable source code.

" + + "

Most of the time a too deep inheritance tree is due to bad object oriented design which has led to systematically use " + + "'inheritance' when 'composition' would suit better.

") +public class DITCheck extends SquidCheck { + + @RuleProperty(description = "Maximum depth of the inheritance tree.", defaultValue = "5") + private Integer max; + + @Override + public void visitClass(SourceClass sourceClass) { + int dit = sourceClass.getInt(Metric.DIT); + if (dit > max) { + CheckMessage message = new CheckMessage(this, "This class has " + dit + + " parents which makes it complex to understand and to maintain."); + message.setLine(sourceClass.getStartAtLine()); + message.setCost(dit - max); + getSourceFile(sourceClass).log(message); + } + } + + public void setMax(int max) { + this.max = max; + } +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/MethodComplexityCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/MethodComplexityCheck.java new file mode 100644 index 00000000000..27361d34deb --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/MethodComplexityCheck.java @@ -0,0 +1,31 @@ +package org.sonar.java.squid.check; + +import org.sonar.check.IsoCategory; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceMethod; +import org.sonar.squid.measures.Metric; + +@Rule(key = "MethodComplexityCheck", name = "MethodComplexityCheck", isoCategory = IsoCategory.Maintainability) +public class MethodComplexityCheck extends SquidCheck { + + @RuleProperty(description = "Threshold.") + private Integer threshold; + + @Override + public void visitMethod(SourceMethod sourceMethod) { + int complexity = sourceMethod.getInt(Metric.COMPLEXITY); + if (complexity > threshold) { + CheckMessage message = new CheckMessage(this, "Method complexity exceeds " + threshold + "."); + message.setLine(sourceMethod.getStartAtLine()); + message.setCost(complexity - threshold); + getSourceFile(sourceMethod).log(message); + } + } + + public void setThreshold(int threshold) { + this.threshold = threshold; + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/SquidCheck.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/SquidCheck.java new file mode 100644 index 00000000000..fe28095de4a --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/check/SquidCheck.java @@ -0,0 +1,12 @@ +package org.sonar.java.squid.check; + +import org.sonar.java.squid.visitor.SquidVisitor; +import org.sonar.squid.api.CodeCheck; + +public class SquidCheck extends SquidVisitor implements CodeCheck { + + public String getKey() { + return getClass().getSimpleName(); + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/visitor/SquidVisitor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/visitor/SquidVisitor.java new file mode 100644 index 00000000000..f50d4f21c21 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/java/squid/visitor/SquidVisitor.java @@ -0,0 +1,28 @@ +package org.sonar.java.squid.visitor; + +import org.sonar.squid.api.CodeVisitor; +import org.sonar.squid.api.SourceClass; +import org.sonar.squid.api.SourceCode; +import org.sonar.squid.api.SourceFile; +import org.sonar.squid.api.SourceMethod; +import org.sonar.squid.indexer.SquidIndex; + +public class SquidVisitor implements CodeVisitor { + + SquidIndex index; + + public void visitClass(SourceClass sourceClass) { + } + + public void visitMethod(SourceMethod sourceMethod) { + } + + protected final SourceFile getSourceFile(SourceCode sourceCode) { + return sourceCode.getParent(SourceFile.class); + } + + public void setSquidIndex(SquidIndex index) { + this.index = index; + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidExecutor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidExecutor.java index bab76dee513..bbc1bb31777 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidExecutor.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidExecutor.java @@ -19,6 +19,11 @@ */ package org.sonar.plugins.squid; +import java.io.File; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.List; + import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.SensorContext; import org.sonar.api.checks.CheckFactory; @@ -29,6 +34,7 @@ import org.sonar.api.utils.TimeProfiler; import org.sonar.java.ast.JavaAstScanner; import org.sonar.java.bytecode.BytecodeScanner; import org.sonar.java.squid.JavaSquidConfiguration; +import org.sonar.java.squid.SquidScanner; import org.sonar.plugins.squid.bridges.Bridge; import org.sonar.plugins.squid.bridges.BridgeFactory; import org.sonar.plugins.squid.bridges.ResourceIndex; @@ -40,11 +46,6 @@ import org.sonar.squid.api.SourcePackage; import org.sonar.squid.indexer.QueryByType; import org.sonar.squid.measures.Metric; -import java.io.File; -import java.nio.charset.Charset; -import java.util.Collection; -import java.util.List; - public final class SquidExecutor { private Squid squid; @@ -52,7 +53,8 @@ public final class SquidExecutor { private boolean bytecodeScanned = false; private CheckFactory checkFactory; - public SquidExecutor(boolean analyzePropertyAccessors, String fieldNamesToExcludeFromLcom4Computation, CheckFactory checkFactory, Charset sourcesCharset) { + public SquidExecutor(boolean analyzePropertyAccessors, String fieldNamesToExcludeFromLcom4Computation, CheckFactory checkFactory, + Charset sourcesCharset) { JavaSquidConfiguration conf = createJavaSquidConfiguration(analyzePropertyAccessors, fieldNamesToExcludeFromLcom4Computation, sourcesCharset); squid = new Squid(conf); @@ -87,6 +89,7 @@ public final class SquidExecutor { scanBytecode(bytecodeFilesOrDirectories); } squid.decorateSourceCodeTreeWith(Metric.values()); + scanSquidIndex(); } public void save(Project project, SensorContext context, NoSonarFilter noSonarFilter) { @@ -153,6 +156,13 @@ public final class SquidExecutor { } } + void scanSquidIndex() { + TimeProfiler profiler = new TimeProfiler(getClass()).start("Java Squid scan"); + SquidScanner squidScanner = squid.register(SquidScanner.class); + squidScanner.scan(); + profiler.stop(); + } + boolean isSourceScanned() { return sourceScanned; } diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidRuleRepository.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidRuleRepository.java index 9c4ae500f29..3b47ff28e18 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidRuleRepository.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidRuleRepository.java @@ -28,15 +28,15 @@ import org.sonar.api.rules.AnnotationRuleParser; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleRepository; import org.sonar.java.ast.check.BreakCheck; -import org.sonar.java.ast.check.ClassComplexityCheck; import org.sonar.java.ast.check.ContinueCheck; -import org.sonar.java.ast.check.MethodComplexityCheck; import org.sonar.java.ast.check.UndocumentedApiCheck; import org.sonar.java.bytecode.check.ArchitectureCheck; import org.sonar.java.bytecode.check.CallToDeprecatedMethodCheck; -import org.sonar.java.bytecode.check.DITCheck; import org.sonar.java.bytecode.check.UnusedPrivateMethodCheck; import org.sonar.java.bytecode.check.UnusedProtectedMethodCheck; +import org.sonar.java.squid.check.ClassComplexityCheck; +import org.sonar.java.squid.check.DITCheck; +import org.sonar.java.squid.check.MethodComplexityCheck; public final class SquidRuleRepository extends RuleRepository { private AnnotationRuleParser ruleParser; @@ -56,8 +56,10 @@ public final class SquidRuleRepository extends RuleRepository { return Arrays.asList( // Bytecode checks (Class) CallToDeprecatedMethodCheck.class, UnusedPrivateMethodCheck.class, UnusedProtectedMethodCheck.class, - ArchitectureCheck.class, DITCheck.class, + ArchitectureCheck.class, // AST checks - UndocumentedApiCheck.class, ContinueCheck.class, BreakCheck.class, ClassComplexityCheck.class, MethodComplexityCheck.class); + UndocumentedApiCheck.class, ContinueCheck.class, BreakCheck.class, ClassComplexityCheck.class, MethodComplexityCheck.class, + // Squid checks + DITCheck.class); } } diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/ClassComplexityCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/ClassComplexityCheckTest.java deleted file mode 100644 index 39692969332..00000000000 --- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/ClassComplexityCheckTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2009 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ - -package org.sonar.java.ast.check; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.sonar.java.ast.SquidTestUtils.getFile; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.java.ast.JavaAstScanner; -import org.sonar.java.squid.JavaSquidConfiguration; -import org.sonar.squid.Squid; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceFile; - -public class ClassComplexityCheckTest { - - private Squid squid; - - @Before - public void setUp() { - squid = new Squid(new JavaSquidConfiguration()); - ClassComplexityCheck check = new ClassComplexityCheck(); - check.setThreshold(5); - squid.registerVisitor(check); - JavaAstScanner scanner = squid.register(JavaAstScanner.class); - scanner.scanFile(getFile("/metrics/branches/NoBranches.java")); - scanner.scanFile(getFile("/metrics/branches/ComplexBranches.java")); - } - - @Test - public void testComplexityExceedsThreshold() { - SourceFile file = (SourceFile) squid.search("ComplexBranches.java"); - assertThat(file.getCheckMessages().size(), is(1)); - CheckMessage message = file.getCheckMessages().iterator().next(); - assertThat(message.getLine(), is(3)); - } - - @Test - public void testComplexityNotExceedsThreshold() { - SourceFile file = (SourceFile) squid.search("NoBranches.java"); - assertThat(file.getCheckMessages().size(), is(0)); - } - -} diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/MethodComplexityCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/MethodComplexityCheckTest.java deleted file mode 100644 index 5f8a73396bd..00000000000 --- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/ast/check/MethodComplexityCheckTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.sonar.java.ast.check; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.sonar.java.ast.SquidTestUtils.getFile; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.java.ast.JavaAstScanner; -import org.sonar.java.squid.JavaSquidConfiguration; -import org.sonar.squid.Squid; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceFile; - -public class MethodComplexityCheckTest { - private Squid squid; - - @Before - public void setUp() { - squid = new Squid(new JavaSquidConfiguration()); - MethodComplexityCheck check = new MethodComplexityCheck(); - check.setThreshold(5); - squid.registerVisitor(check); - JavaAstScanner scanner = squid.register(JavaAstScanner.class); - scanner.scanFile(getFile("/metrics/branches/ComplexBranches.java")); - } - - @Test - public void testMethodComplexityExceedsThreshold() { - SourceFile file = (SourceFile) squid.search("ComplexBranches.java"); - assertThat(file.getCheckMessages().size(), is(1)); - CheckMessage message = file.getCheckMessages().iterator().next(); - assertThat(message.getLine(), is(10)); - } -} diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/bytecode/check/DITCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/bytecode/check/DITCheckTest.java deleted file mode 100644 index bbe16d51117..00000000000 --- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/bytecode/check/DITCheckTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sonar.java.bytecode.check; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.sonar.java.ast.SquidTestUtils.getFile; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.sonar.java.ast.JavaAstScanner; -import org.sonar.java.bytecode.BytecodeScanner; -import org.sonar.java.squid.JavaSquidConfiguration; -import org.sonar.squid.Squid; -import org.sonar.squid.api.CheckMessage; -import org.sonar.squid.api.SourceFile; - -public class DITCheckTest { - - private static Squid squid; - - @BeforeClass - public static void setup() { - squid = new Squid(new JavaSquidConfiguration()); - squid.register(JavaAstScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/src")); - DITCheck check = new DITCheck(); - check.setMax(1); - squid.registerVisitor(check); - squid.register(BytecodeScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/bin")); - } - - @Test - public void testDepthOfInheritanceGreaterThanMaximum() { - SourceFile file = (SourceFile) squid.search("UnusedProtectedMethod.java"); - assertThat(file.getCheckMessages().size(), is(1)); - CheckMessage message = file.getCheckMessages().iterator().next(); - assertThat(message.getLine(), is(7)); - } - - @Test - public void testDepthOfInheritanceLowerThanMaximum() { - SourceFile file = (SourceFile) squid.search("Job.java"); - assertThat(file.getCheckMessages().size(), is(0)); - } - -} diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/ClassComplexityCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/ClassComplexityCheckTest.java new file mode 100644 index 00000000000..24f7f02f261 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/ClassComplexityCheckTest.java @@ -0,0 +1,68 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +package org.sonar.java.squid.check; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.sonar.java.ast.SquidTestUtils.getFile; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.java.ast.JavaAstScanner; +import org.sonar.java.squid.JavaSquidConfiguration; +import org.sonar.java.squid.SquidScanner; +import org.sonar.squid.Squid; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceFile; +import org.sonar.squid.measures.Metric; + +public class ClassComplexityCheckTest { + + private Squid squid; + + @Before + public void setUp() { + squid = new Squid(new JavaSquidConfiguration()); + ClassComplexityCheck check = new ClassComplexityCheck(); + check.setThreshold(5); + squid.registerVisitor(check); + JavaAstScanner scanner = squid.register(JavaAstScanner.class); + scanner.scanFile(getFile("/metrics/branches/NoBranches.java")); + scanner.scanFile(getFile("/metrics/branches/ComplexBranches.java")); + squid.decorateSourceCodeTreeWith(Metric.values()); + squid.register(SquidScanner.class).scan(); + } + + @Test + public void testComplexityExceedsThreshold() { + SourceFile file = (SourceFile) squid.search("ComplexBranches.java"); + assertThat(file.getCheckMessages().size(), is(1)); + CheckMessage message = file.getCheckMessages().iterator().next(); + assertThat(message.getLine(), is(3)); + } + + @Test + public void testComplexityNotExceedsThreshold() { + SourceFile file = (SourceFile) squid.search("NoBranches.java"); + assertThat(file.getCheckMessages().size(), is(0)); + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/DITCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/DITCheckTest.java new file mode 100644 index 00000000000..51e9a215704 --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/DITCheckTest.java @@ -0,0 +1,46 @@ +package org.sonar.java.squid.check; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.sonar.java.ast.SquidTestUtils.getFile; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.sonar.java.ast.JavaAstScanner; +import org.sonar.java.bytecode.BytecodeScanner; +import org.sonar.java.squid.JavaSquidConfiguration; +import org.sonar.java.squid.SquidScanner; +import org.sonar.squid.Squid; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceFile; + +public class DITCheckTest { + + private static Squid squid; + + @BeforeClass + public static void setup() { + squid = new Squid(new JavaSquidConfiguration()); + DITCheck check = new DITCheck(); + check.setMax(1); + squid.registerVisitor(check); + squid.register(JavaAstScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/src")); + squid.register(BytecodeScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/bin")); + squid.register(SquidScanner.class).scan(); + } + + @Test + public void testDepthOfInheritanceGreaterThanMaximum() { + SourceFile file = (SourceFile) squid.search("UnusedProtectedMethod.java"); + assertThat(file.getCheckMessages().size(), is(1)); + CheckMessage message = file.getCheckMessages().iterator().next(); + assertThat(message.getLine(), is(7)); + } + + @Test + public void testDepthOfInheritanceLowerThanMaximum() { + SourceFile file = (SourceFile) squid.search("Job.java"); + assertThat(file.getCheckMessages().size(), is(0)); + } + +} diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/MethodComplexityCheckTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/MethodComplexityCheckTest.java new file mode 100644 index 00000000000..5533ca8e18d --- /dev/null +++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/java/squid/check/MethodComplexityCheckTest.java @@ -0,0 +1,39 @@ +package org.sonar.java.squid.check; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.sonar.java.ast.SquidTestUtils.getFile; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.java.ast.JavaAstScanner; +import org.sonar.java.squid.JavaSquidConfiguration; +import org.sonar.java.squid.SquidScanner; +import org.sonar.squid.Squid; +import org.sonar.squid.api.CheckMessage; +import org.sonar.squid.api.SourceFile; +import org.sonar.squid.measures.Metric; + +public class MethodComplexityCheckTest { + private Squid squid; + + @Before + public void setUp() { + squid = new Squid(new JavaSquidConfiguration()); + MethodComplexityCheck check = new MethodComplexityCheck(); + check.setThreshold(5); + squid.registerVisitor(check); + JavaAstScanner scanner = squid.register(JavaAstScanner.class); + scanner.scanFile(getFile("/metrics/branches/ComplexBranches.java")); + squid.decorateSourceCodeTreeWith(Metric.values()); + squid.register(SquidScanner.class).scan(); + } + + @Test + public void testMethodComplexityExceedsThreshold() { + SourceFile file = (SourceFile) squid.search("ComplexBranches.java"); + assertThat(file.getCheckMessages().size(), is(1)); + CheckMessage message = file.getCheckMessages().iterator().next(); + assertThat(message.getLine(), is(10)); + } +} -- cgit v1.2.3