Skip to content

Commit

Permalink
Added code climate configurations and updated circle ci configurations.
Browse files Browse the repository at this point in the history
  • Loading branch information
ankit-agrawal11 committed Mar 26, 2018
1 parent 1677855 commit 97afa68
Show file tree
Hide file tree
Showing 14 changed files with 752 additions and 11 deletions.
29 changes: 20 additions & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand All @@ -20,7 +20,7 @@ jobs:
# Customize the JVM maximum heap limit
JVM_OPTS: -Xmx3200m
TERM: dumb

steps:
- checkout

Expand All @@ -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
10 changes: 10 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: "2"

plugins:
codenarc:
enabled: true
channel: "beta"
config: "./code-climate-codenarc/codenarc.groovy"

exclude_patterns:
- "code-climate-codenarc/"
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
changelog.md merge=union
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}

Expand Down Expand Up @@ -110,6 +110,7 @@ ccJacocoExt {
]

includeIntegrationTest = true

}

jar {
Expand Down
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## [0.0.9] - [Unreleased]
## [0.0.9] - 2018-03-26

### Added
- Functionality to externalize the scheduling of UpdateEmbeddedInstancesJob.
Expand Down
99 changes: 99 additions & 0 deletions code-climate-codenarc/CanNotModifyReferenceRule.groovy
Original file line number Diff line number Diff line change
@@ -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<String> currentMethodParameterNames = []
private List<String> 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
}
}
}

42 changes: 42 additions & 0 deletions code-climate-codenarc/EmptyLineAfterClosingBraceRule.groovy
Original file line number Diff line number Diff line change
@@ -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<String> 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.'))
}
}
}
}
38 changes: 38 additions & 0 deletions code-climate-codenarc/GrailsDomainTimestampFieldsRule.groovy
Original file line number Diff line number Diff line change
@@ -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")
}
}
}
71 changes: 71 additions & 0 deletions code-climate-codenarc/GrailsMaxForListQueriesRule.groovy
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Loading

0 comments on commit 97afa68

Please sign in to comment.