diff --git a/.circleci/config.yml b/.circleci/config.yml index 170f97c..77418d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: docker: # specify the version you desire here - image: circleci/openjdk:8-jdk - + # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images # documented at https://circleci.com/docs/2.0/circleci-images/ @@ -20,7 +20,7 @@ jobs: # Customize the JVM maximum heap limit JVM_OPTS: -Xmx3200m TERM: dumb - + steps: - checkout @@ -33,18 +33,29 @@ jobs: - run: chmod +x ./.circleci/mavenCredsSetup.sh - run: ./.circleci/mavenCredsSetup.sh - - run: gradle dependencies + - run: ./gradlew dependencies - save_cache: paths: - ~/.m2 key: v1-dependencies-{{ checksum "build.gradle" }} - # run tests! - - run: gradle clean test + # Code climate coverage-test-reporter-id + - run: echo "export CC_TEST_REPORTER_ID=$CC_TEST_REPORTER_ID" >> $BASH_ENV + + # Code climate test coverage reporter configuration + - run: + name: Setup Code Climate test-reporter + command: | + cp ./test-reporter-custom-builds/test-reporter-0.4.6-RC1-linux-amd64 ./cc-test-reporter + chmod +x ./cc-test-reporter + - run: + name: Run tests + command: | + ./cc-test-reporter before-build + ./gradlew clean test integrationTest cc-jacoco + ./cc-test-reporter format-coverage --input-type jacoco -d ./build/jacoco/jacocoXml/jacoco.xml + ./cc-test-reporter upload-coverage #run custom gradle tasks - - run: gradle cc-codenarc - - run: gradle simian - - run: gradle test cc-jacoco - + - run: ./gradlew clean classes cc-codenarc diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..e215fd0 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,10 @@ +version: "2" + +plugins: + codenarc: + enabled: true + channel: "beta" + config: "./code-climate-codenarc/codenarc.groovy" + +exclude_patterns: + - "code-climate-codenarc/" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6487cdc --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +changelog.md merge=union diff --git a/README.md b/README.md index ef8ec9c..1d6a7c7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ ## Mongo Update Embedded Plugin for Grails 3.1.x +[![Maintainability](https://api.codeclimate.com/v1/badges/74a1adc38f8680230299/maintainability)](https://codeclimate.com/repos/5ab8e30d68478e0271005a99/maintainability) +[![Test Coverage](https://api.codeclimate.com/v1/badges/74a1adc38f8680230299/test_coverage)](https://codeclimate.com/repos/5ab8e30d68478e0271005a99/test_coverage) + Latest Version (0.0.9) ### Installation diff --git a/build.gradle b/build.gradle index 37f5ec1..e374c5d 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { } dependencies { classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "com.causecode.plugins:gradle-code-quality:1.0.0" + classpath "com.causecode.plugins:gradle-code-quality:1.0.2" } } @@ -110,6 +110,7 @@ ccJacocoExt { ] includeIntegrationTest = true + } jar { diff --git a/changelog.md b/changelog.md index 2a7478c..e629f7e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ # Changelog -## [0.0.9] - [Unreleased] +## [0.0.9] - 2018-03-26 ### Added - Functionality to externalize the scheduling of UpdateEmbeddedInstancesJob. diff --git a/code-climate-codenarc/CanNotModifyReferenceRule.groovy b/code-climate-codenarc/CanNotModifyReferenceRule.groovy new file mode 100644 index 0000000..7856583 --- /dev/null +++ b/code-climate-codenarc/CanNotModifyReferenceRule.groovy @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.expr.BinaryExpression +import org.codehaus.groovy.ast.expr.ClosureExpression +import org.codehaus.groovy.ast.expr.PropertyExpression +import org.codenarc.rule.AbstractAstVisitor +import org.codenarc.rule.AbstractAstVisitorRule + +import java.util.stream.Collectors + +/** + * Codenarc rule to avoid manipulating method/closure parameter. + * @author Kshitij Mandloi + * @since 1.0.1 + */ +class CanNotModifyReferenceRule extends AbstractAstVisitorRule { + + String name = 'CannotModifyReference' + int priority = 1 + String description = 'Parameters of method and closure cannot be modified. Use a temporary variable.' + Class astVisitorClass = CanNotModifyReferenceAstVisitor + +} + +class CanNotModifyReferenceAstVisitor extends AbstractAstVisitor { + + private List currentMethodParameterNames = [] + private List currentClosureParameterNames = [] + + @Override + protected void visitMethodEx(MethodNode node) { + currentMethodParameterNames = Arrays.stream(node.parameters) + .map { Parameter parameter -> parameter.name }.collect(Collectors.toList()) + super.visitMethodEx(node) + } + + @Override + protected void visitMethodComplete(MethodNode node) { + super.visitMethodComplete(node) + currentMethodParameterNames = [] + } + + @Override + void visitClosureExpression(ClosureExpression expression) { + String parameterNames = expression.parameters?.text ?: [] + currentClosureParameterNames.addAll(parameterNames) + super.visitClosureExpression(expression) + currentClosureParameterNames.removeAll(parameterNames) + } + + @Override + void visitBinaryExpression(BinaryExpression expression) { + if (isFirstVisit(expression) && isManipulatingAParameter(expression)) { + String name = expression.leftExpression.text + addViolation(expression, "The method parameter [$name] in class $currentClassName was manipulated. " + + "Use a temporary variable instead.") + } + super.visitBinaryExpression(expression) + } + + /** + * Utility method to check if a method is manipulating a parameter. + * @param expression + * @return true, if parameter manipulation is happening + */ + private boolean isManipulatingAParameter(BinaryExpression expression) { + expression.operation.text in ['=', '+=', '-=', '*=', '/=', '**'] && + expression.leftExpression instanceof PropertyExpression && + isCurrentParameterName(expression.leftExpression.text) + } + + /** + * Utility method to check if the leftExpression contains current method closure/parameter or not. + * @param name + * @return true, if leftExpression is current method/closure parameter + */ + private boolean isCurrentParameterName(String name) { + if (!name) { + return false + } + + List tokens = [] + tokens.addAll(currentMethodParameterNames) + tokens.addAll(currentClosureParameterNames) + + return tokens.stream().anyMatch() { String param -> + name.split('\\.')[0] == param + } + } +} + diff --git a/code-climate-codenarc/EmptyLineAfterClosingBraceRule.groovy b/code-climate-codenarc/EmptyLineAfterClosingBraceRule.groovy new file mode 100644 index 0000000..0d738a0 --- /dev/null +++ b/code-climate-codenarc/EmptyLineAfterClosingBraceRule.groovy @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import org.codenarc.rule.AbstractRule +import org.codenarc.source.SourceCode + +/** + * This is a custom rule that validates the presence of an empty line after the closing brace. + * The case is ignored if there is another closing brace on the next line or it's a loop. + * + * @author Ankit Agrawal + * @since 0.0.9 + */ +class EmptyLineAfterClosingBraceRule extends AbstractRule { + + String name = 'EmptyLineAfterClosingBraceRule' + String description = 'There should be an empty line after the closing (\"}\") brace.' + int priority = 2 + + @Override + void applyTo(SourceCode sourceCode, List violations) { + + List lines = sourceCode.lines + + for (int index = 1; index < lines.size(); index++) { + String line = lines[index].trim() + String previousLine = lines[index - 1].trim() + + if (previousLine.contains('}') && !(previousLine.contains('{')) && !(previousLine.contains('})')) && + !line.contains('}') && !(line.isEmpty())) { + violations.add(createViolation(index, previousLine, + 'There should be an empty line after the closing brace.')) + } + } + } +} diff --git a/code-climate-codenarc/GrailsDomainTimestampFieldsRule.groovy b/code-climate-codenarc/GrailsDomainTimestampFieldsRule.groovy new file mode 100644 index 0000000..633dfaa --- /dev/null +++ b/code-climate-codenarc/GrailsDomainTimestampFieldsRule.groovy @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import org.codenarc.rule.AbstractAstVisitorRule +import org.codenarc.rule.AbstractAstVisitor +import org.codenarc.rule.grails.GrailsUtil +import org.codehaus.groovy.ast.ClassNode + +/** + * This is a custom codenarc rule that checks that all domains should have timestamp fields + * + * @author Ankit Agrawal + * @since 0.0.9 + */ +class GrailsDomainTimestampFieldsRule extends AbstractAstVisitorRule { + String name = 'GrailsDomainTimestampFields' + String description = 'All domain classes should have timestamp fields.' + int priority = 1 + Class astVisitorClass = GrailsDomainTimestampFieldsRuleAstVisitor + String applyToFilesMatching = GrailsUtil.DOMAIN_FILES +} + +class GrailsDomainTimestampFieldsRuleAstVisitor extends AbstractAstVisitor { + + @Override + void visitClassComplete(ClassNode classNode) { + if (!classNode.enum && !classNode.fields.name.containsAll(['dateCreated', 'lastUpdated'])) { + addViolation(classNode, "The domain class $classNode.name should contain timestamp fields " + + "dateCreated and lastUpdated") + } + } +} diff --git a/code-climate-codenarc/GrailsMaxForListQueriesRule.groovy b/code-climate-codenarc/GrailsMaxForListQueriesRule.groovy new file mode 100644 index 0000000..29eb940 --- /dev/null +++ b/code-climate-codenarc/GrailsMaxForListQueriesRule.groovy @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import org.codehaus.groovy.ast.expr.ClosureExpression +import org.codehaus.groovy.ast.expr.MapExpression +import org.codehaus.groovy.ast.expr.MethodCallExpression +import org.codenarc.rule.AbstractAstVisitorRule +import org.codenarc.rule.AbstractMethodCallExpressionVisitor +import org.codenarc.util.AstUtil + +/** + * This is a custom codenarc rule that checks that all methods that returns a list from database must implement max + * parameters. + * + * @author Nikhil Sharma + * @since 0.0.1 + */ +class GrailsMaxForListQueriesRule extends AbstractAstVisitorRule { + String name = 'GrailsMaxForListQueries' + String description = 'Any call to database that returns a list must have max value set.' + int priority = 1 + Class astVisitorClass = GrailsMaxForListQueriesRuleAstVisitor +} + +class GrailsMaxForListQueriesRuleAstVisitor extends AbstractMethodCallExpressionVisitor { + + @SuppressWarnings(['Instanceof']) + @Override + void visitMethodCallExpression(MethodCallExpression call) { + String errorMessage = 'Add max parameter for this call' + boolean isViolation + + def arguments = AstUtil.getMethodArguments(call) + String methodName = call.methodAsString + + if (methodName == 'withCriteria') { + arguments.each { argument -> + if (argument instanceof ClosureExpression) { + if (!argument.code.text.contains('maxResults') && !argument.code.text.contains('rowCount')) { + isViolation = true + } + } + } + } + + if (methodName == 'findAll' || methodName == 'list') { + if (!arguments) { + isViolation = true + } + + arguments.each { argument -> + if (argument instanceof MapExpression) { + def maxAsKey = argument.mapEntryExpressions.find { mapEntryExpression -> + mapEntryExpression.keyExpression.text == 'max' + } + isViolation = !maxAsKey + } + } + } + + if (isViolation) { + addViolation(call, errorMessage) + } + } +} diff --git a/code-climate-codenarc/MapAsMethodParameterRule.groovy b/code-climate-codenarc/MapAsMethodParameterRule.groovy new file mode 100644 index 0000000..2dc7a08 --- /dev/null +++ b/code-climate-codenarc/MapAsMethodParameterRule.groovy @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codenarc.rule.AbstractAstVisitorRule +import org.codenarc.rule.AbstractMethodVisitor + +/** + * This is a custom rule that validates the method arguments. Conditions for violation - + * If method has less than 3 arguments and any of them is a Map. + * + * @author Ankit Agrawal + * @since 0.0.9 + */ +class MapAsMethodParameterRule extends AbstractAstVisitorRule { + String name = 'MapAsMethodParameterRule' + String description = 'Verifies that the method parameters are valid. If the number of parameters are less' + + ' than 3 and any of them is a Map then this error is thrown. It is advised to pass separate parameters ' + + ' instead of passing the complete Map.' + int priority = 3 + Class astVisitorClass = MapAsMethodParameterRuleAstVisitor +} + +class MapAsMethodParameterRuleAstVisitor extends AbstractMethodVisitor { + + @Override + void visitMethod(MethodNode node) { + Parameter[] arguments = node.parameters + int numberOfArgs = arguments.size() + + arguments.each { argument -> + if (argument.type.toString() == 'Map' && numberOfArgs < 3) { + addViolation(node, 'Passing the complete request parameter as arguments should be avoided.') + } + } + } +} \ No newline at end of file diff --git a/code-climate-codenarc/codenarc.groovy b/code-climate-codenarc/codenarc.groovy new file mode 100644 index 0000000..6aaf37d --- /dev/null +++ b/code-climate-codenarc/codenarc.groovy @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2011-Present, CauseCode Technologies Pvt Ltd, India. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are not permitted. + */ +package com.causecode.quality.configurations.codenarc + +import groovy.transform.EqualsAndHashCode + +ruleset { + // rulesets/basic.xml + AssertWithinFinallyBlock + AssignmentInConditional + BigDecimalInstantiation + BitwiseOperatorInConditional + BooleanGetBoolean + BrokenNullCheck + BrokenOddnessCheck + ClassForName + ComparisonOfTwoConstants + ComparisonWithSelf + ConstantAssertExpression + ConstantIfExpression + ConstantTernaryExpression + DeadCode + DoubleNegative + DuplicateCaseStatement + DuplicateMapKey + DuplicateSetValue + EmptyCatchBlock + EmptyClass + EmptyElseBlock + EmptyFinallyBlock + EmptyForStatement + EmptyIfStatement + EmptyInstanceInitializer + EmptyMethod + EmptyStaticInitializer + EmptySwitchStatement + EmptySynchronizedStatement + EmptyTryBlock + EmptyWhileStatement + EqualsAndHashCode + EqualsOverloaded + ExplicitGarbageCollection + ForLoopShouldBeWhileLoop + HardCodedWindowsFileSeparator + HardCodedWindowsRootDirectory + IntegerGetInteger + MultipleUnaryOperators + RandomDoubleCoercedToZero + RemoveAllOnSelf + ReturnFromFinallyBlock + ThrowExceptionFromFinallyBlock + + // rulesets/braces.xml + ElseBlockBraces(bracesRequiredForElseIf: false) + ForStatementBraces + IfStatementBraces + WhileStatementBraces + + // rulesets/concurrency.xml + BusyWait + DoubleCheckedLocking + InconsistentPropertyLocking + InconsistentPropertySynchronization + NestedSynchronization + StaticCalendarField + StaticConnection + StaticDateFormatField + StaticMatcherField + StaticSimpleDateFormatField + SynchronizedMethod + SynchronizedOnBoxedPrimitive + SynchronizedOnGetClass + SynchronizedOnReentrantLock + SynchronizedOnString + SynchronizedOnThis + SynchronizedReadObjectMethod + SystemRunFinalizersOnExit + ThisReferenceEscapesConstructor + ThreadGroup + ThreadLocalNotStaticFinal + ThreadYield + UseOfNotifyMethod + VolatileArrayField + VolatileLongOrDoubleField + WaitOutsideOfWhileLoop + + // rulesets/convention.xml + ConfusingTernary + CouldBeElvis + HashtableIsObsolete + IfStatementCouldBeTernary + InvertedIfElse + LongLiteralWithLowerCaseL + // NoDef + ParameterReassignment + TernaryCouldBeElvis + VectorIsObsolete + + // rulesets/design.xml + AbstractClassWithPublicConstructor + AbstractClassWithoutAbstractMethod + AssignmentToStaticFieldFromInstanceMethod + BooleanMethodReturnsNull + BuilderMethodWithSideEffects + CloneableWithoutClone + CloseWithoutCloseable + CompareToWithoutComparable + ConstantsOnlyInterface + EmptyMethodInAbstractClass + FinalClassWithProtectedMember + ImplementationAsType + Instanceof + LocaleSetDefault + NestedForLoop + PrivateFieldCouldBeFinal + PublicInstanceField + ReturnsNullInsteadOfEmptyArray + ReturnsNullInsteadOfEmptyCollection + SimpleDateFormatMissingLocale + StatelessSingleton + ToStringReturnsNull + + // rulesets/enhanced.xml + // CloneWithoutCloneable, causing compilation errors -> https://github.com/CodeNarc/CodeNarc/issues/123 + // UnsafeImplementationAsMap + JUnitAssertEqualsConstantActualValue + + // rulesets/exceptions.xml + CatchArrayIndexOutOfBoundsException + CatchError + CatchException + CatchIllegalMonitorStateException + CatchIndexOutOfBoundsException + CatchNullPointerException + CatchRuntimeException + CatchThrowable + ConfusingClassNamedException + ExceptionExtendsError + ExceptionExtendsThrowable + ExceptionNotThrown + MissingNewInThrowStatement + ReturnNullFromCatchBlock + SwallowThreadDeath + ThrowError + ThrowException + ThrowNullPointerException + ThrowRuntimeException + ThrowThrowable + + // rulesets/formatting.xml + BlankLineBeforePackage + BracesForClass + BracesForForLoop + BracesForIfElse + BracesForMethod + BracesForTryCatchFinally + ClassJavadoc + ClosureStatementOnOpeningLineOfMultipleLineClosure + ConsecutiveBlankLines + FileEndsWithoutNewline + LineLength + MissingBlankLineAfterImports + MissingBlankLineAfterPackage + SpaceAfterCatch + SpaceAfterClosingBrace + SpaceAfterComma + SpaceAfterFor + SpaceAfterIf + SpaceAfterOpeningBrace + SpaceAfterSemicolon + SpaceAfterSwitch + SpaceAfterWhile + SpaceAroundClosureArrow +// SpaceAroundMapEntryColon(characterAfterColonRegex: /\s/) + SpaceAroundOperator + SpaceBeforeClosingBrace + SpaceBeforeOpeningBrace + TrailingWhitespace + + // rulesets/generic.xml + IllegalClassMember + IllegalClassReference + IllegalPackageReference + IllegalRegex + IllegalString + RequiredRegex + RequiredString + StatelessClass + + // rulesets/grails.xml + GrailsDomainHasEquals + GrailsDomainHasToString + GrailsDomainReservedSqlKeywordName + GrailsDomainWithServiceReference + GrailsDuplicateConstraint + GrailsDuplicateMapping + GrailsMassAssignment + GrailsPublicControllerMethod + GrailsServletContextReference + GrailsStatelessService { + ignoreFieldNames = 'dataSource,messageSource,grails*,gspRenderer,groovyPageRenderer,stringAsGspRenderer,' + + '*Service,scope,sessionFactory,transactional,elasticSearchHelper' + } + + // Custom rule for Grails max parameter in list queries. + rule('file:./code-climate-codenarc/GrailsMaxForListQueriesRule.groovy') + + // Custom rule for timestamp fields in Grails domain classes. + rule('file:./code-climate-codenarc/GrailsDomainTimestampFieldsRule.groovy') + + // Custom rule validating empty line after closing brace. + rule('file:./code-climate-codenarc/EmptyLineAfterClosingBraceRule.groovy') + + // Custom rule validating method arguments. + rule('file:./code-climate-codenarc/MapAsMethodParameterRule.groovy') + + // Custom rule to avoid manipulation of method/closure parameters + rule('file:./code-climate-codenarc/CanNotModifyReferenceRule.groovy') + + // rulesets/groovyism.xml + AssignCollectionSort + AssignCollectionUnique + ClosureAsLastMethodParameter + CollectAllIsDeprecated + ConfusingMultipleReturns + ExplicitArrayListInstantiation + ExplicitCallToAndMethod + ExplicitCallToCompareToMethod + ExplicitCallToDivMethod + ExplicitCallToEqualsMethod + ExplicitCallToGetAtMethod + ExplicitCallToLeftShiftMethod + ExplicitCallToMinusMethod + ExplicitCallToModMethod + ExplicitCallToMultiplyMethod + ExplicitCallToOrMethod + ExplicitCallToPlusMethod + ExplicitCallToPowerMethod + ExplicitCallToRightShiftMethod + ExplicitCallToXorMethod + ExplicitHashMapInstantiation + ExplicitHashSetInstantiation + ExplicitLinkedHashMapInstantiation + ExplicitLinkedListInstantiation + ExplicitStackInstantiation + ExplicitTreeSetInstantiation + GStringAsMapKey + GStringExpressionWithinString + GetterMethodCouldBeProperty { + ignoreMethodsWithOverrideAnnotation = true + } + GroovyLangImmutable + UseCollectMany + UseCollectNested + + // rulesets/imports.xml + DuplicateImport + ImportFromSamePackage + ImportFromSunPackages + MisorderedStaticImports + UnnecessaryGroovyImport +// UnusedImport + NoWildcardImports + + // rulesets/jdbc.xml + DirectConnectionManagement + JdbcConnectionReference + JdbcResultSetReference + JdbcStatementReference + + // rulesets/junit.xml + ChainedTest + CoupledTestCase + JUnitAssertAlwaysFails + JUnitAssertAlwaysSucceeds + JUnitFailWithoutMessage + JUnitLostTest + JUnitPublicField + JUnitPublicNonTestMethod + JUnitPublicProperty + JUnitSetUpCallsSuper + JUnitStyleAssertions + JUnitTearDownCallsSuper + JUnitTestMethodWithoutAssert + JUnitUnnecessarySetUp + JUnitUnnecessaryTearDown + JUnitUnnecessaryThrowsException + SpockIgnoreRestUsed + UnnecessaryFail + UseAssertEqualsInsteadOfAssertTrue + UseAssertFalseInsteadOfNegation + UseAssertNullInsteadOfAssertEquals + UseAssertSameInsteadOfAssertTrue + UseAssertTrueInsteadOfAssertEquals + UseAssertTrueInsteadOfNegation + + // rulesets/logging.xml + LoggerForDifferentClass + LoggerWithWrongModifiers + LoggingSwallowsStacktrace + MultipleLoggers + PrintStackTrace + Println + SystemErrPrint + SystemOutPrint + + // rulesets/naming.xml + AbstractClassName + ClassName { + regex = '^[A-Z][\\$a-zA-Z0-9]*$' + } + ClassNameSameAsFilename + ConfusingMethodName + FactoryMethodName { + regex = 'build.*' + } + FieldName { + regex = '^_?[a-z][a-zA-Z0-9]*$' + finalRegex = '^[A-Z][A-Z_0-9]*$' + staticFinalRegex = '^logger$|^[A-Z][A-Z_0-9]*$|^serialVersionUID$' + } + InterfaceName + MethodName { + regex = '^[a-z][\\$_a-zA-Z0-9]*$|^.*\\s.*$' + } + ObjectOverrideMisspelledMethodName + PackageName + ParameterName + PropertyName + VariableName { + finalRegex = '^[a-z][a-zA-Z0-9]*$' + } + + // rulesets/security.xml + FileCreateTempFile + InsecureRandom + JavaIoPackageAccess + NonFinalPublicField + NonFinalSubclassOfSensitiveInterface + ObjectFinalize + PublicFinalizeMethod + SystemExit + UnsafeArrayDeclaration + + // rulesets/serialization.xml + EnumCustomSerializationIgnored + SerialPersistentFields + SerialVersionUID + SerializableClassMustDefineSerialVersionUID + + // rulesets/size.xml + AbcMetric // Requires the GMetrics jar + ClassSize + // CrapMetric // Requires the GMetrics jar and a Cobertura coverage file + CyclomaticComplexity // Requires the GMetrics jar + MethodCount + MethodSize + NestedBlockDepth + ParameterCount + + // rulesets/unnecessary.xml + AddEmptyString + ConsecutiveLiteralAppends + ConsecutiveStringConcatenation + UnnecessaryBigDecimalInstantiation + UnnecessaryBigIntegerInstantiation + UnnecessaryBooleanExpression + UnnecessaryBooleanInstantiation + UnnecessaryCallForLastElement + UnnecessaryCallToSubstring + UnnecessaryCast + UnnecessaryCatchBlock + UnnecessaryCollectCall + UnnecessaryCollectionCall + UnnecessaryConstructor + UnnecessaryDefInFieldDeclaration + UnnecessaryDefInMethodDeclaration + UnnecessaryDefInVariableDeclaration + UnnecessaryDotClass + UnnecessaryDoubleInstantiation + UnnecessaryElseStatement + UnnecessaryFinalOnPrivateMethod + UnnecessaryFloatInstantiation + UnnecessaryGString + UnnecessaryGetter + UnnecessaryIfStatement + UnnecessaryInstanceOfCheck + UnnecessaryInstantiationToGetClass + UnnecessaryIntegerInstantiation + UnnecessaryLongInstantiation + UnnecessaryModOne + UnnecessaryNullCheck + UnnecessaryNullCheckBeforeInstanceOf + UnnecessaryObjectReferences + UnnecessaryOverridingMethod + UnnecessaryPackageReference + UnnecessaryParenthesesForMethodCallWithClosure + UnnecessaryPublicModifier + // UnnecessaryReturnKeyword + UnnecessarySelfAssignment + UnnecessarySemicolon + UnnecessaryStringInstantiation + UnnecessarySubstring + UnnecessaryTernaryExpression + UnnecessaryToString + UnnecessaryTransientModifier + + // rulesets/unused.xml + UnusedArray + UnusedMethodParameter + UnusedObject + UnusedPrivateField + UnusedPrivateMethod + UnusedPrivateMethodParameter + UnusedVariable +} diff --git a/test-reporter-custom-builds/test-reporter-0.4.6-RC1-darwin-amd64 b/test-reporter-custom-builds/test-reporter-0.4.6-RC1-darwin-amd64 new file mode 100755 index 0000000..cfe3f2c Binary files /dev/null and b/test-reporter-custom-builds/test-reporter-0.4.6-RC1-darwin-amd64 differ diff --git a/test-reporter-custom-builds/test-reporter-0.4.6-RC1-linux-amd64 b/test-reporter-custom-builds/test-reporter-0.4.6-RC1-linux-amd64 new file mode 100755 index 0000000..44dd80e Binary files /dev/null and b/test-reporter-custom-builds/test-reporter-0.4.6-RC1-linux-amd64 differ