diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..3e18c66 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,108 @@ +version: 2 +references: + + cache_key: &cache_key + key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} + + restore_cache: &restore_cache + restore_cache: + <<: *cache_key + + save_cache: &save_cache + save_cache: + <<: *cache_key + paths: + ~/.gradle + + workspace: &workspace + ~/workspace + + attach_release_workspace: &attach_release_workspace + attach_workspace: + at: *workspace + + persist_release_workspace: &persist_release_workspace + persist_to_workspace: + root: *workspace + paths: + - app/build + + android_config: &android_config + working_directory: *workspace + docker: + - image: circleci/android:api-28-alpha + environment: + TERM: dumb + JAVA_OPTIONS: "-Xmx2048m" + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m"' + +jobs: + build: + <<: *android_config + steps: + - checkout + - *restore_cache + - run: + name: Chmod permissions + command: sudo chmod +x ./gradlew + - run: + name: Download Dependencies + command: ./gradlew androidDependencies + - *save_cache + - *persist_release_workspace + + detekt: + <<: *android_config + steps: + - checkout + - *attach_release_workspace + - *restore_cache + - run: + name: Chmod permissions + command: sudo chmod +x ./gradlew + - run: + name: Run Detekt Checkstyle + command: ./gradlew detekt + - store_artifacts: + path: app/build/reports/ + destination: /reports/ + + test_unit: + <<: *android_config + steps: + - checkout + - *attach_release_workspace + - *restore_cache + - run: + name: Chmod permissions + command: sudo chmod +x ./gradlew + - run: + name: Run unit tests + command: ./gradlew test -no-daemon -Pkotlin.incremental=false --max-workers=2 + - store_artifacts: + path: app/build/reports/ + destination: /reports/ + - store_test_results: + path: app/build/test-results/ + destination: /test-results/ + +workflows: + version: 2 + workflow: + jobs: + - build: + filters: + tags: + only: /^.*/ + - detekt: + requires: + - build + filters: + tags: + only: /^.*/ + - test_unit: + requires: + - build + filters: + tags: + only: /^.*/ \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a84fa06..43615c1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,6 +22,22 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + detekt { + version = "1.0.0-RC14" + input = files("${project.rootDir}/${project.getName()}/src/main/kotlin") + config = files("${project.rootDir}/detekt/detekt-config.yml") + filters = ".*test.*,.*/resources/.*,.*/tmp/.*" + reports { + xml { + enabled = true + destination = file("build/reports/detekt.xml") + } + html { + enabled = true + destination = file("build/reports/detekt.html") + } + } + } } dependencies { diff --git a/build.gradle b/build.gradle index 824b6ce..e7cdb2c 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,17 @@ buildscript { } } +plugins { + id("io.gitlab.arturbosch.detekt").version("1.0.0-RC14") +} + +detekt { + toolVersion = "1.0.0-RC14" + input = files("src/main/java") + filters = ".*/resources/.*,.*/build/.*" + baseline = file("my-detekt-baseline.xml") // Just if you want to create a baseline file. +} + allprojects { repositories { google() diff --git a/detekt/detekt-config.yml b/detekt/detekt-config.yml new file mode 100644 index 0000000..396057b --- /dev/null +++ b/detekt/detekt-config.yml @@ -0,0 +1,362 @@ +autoCorrect: true +failFast: false + +test-pattern: # Configure exclusions for test sources + active: true + patterns: # Test file regexes + - '.*/test/.*' + - '.*Test.kt' + - '.*Spec.kt' + exclude-rule-sets: + - 'comments' + exclude-rules: + - 'NamingRules' + - 'WildcardImport' + - 'MagicNumber' + - 'MaxLineLength' + - 'LateinitUsage' + - 'StringLiteralDuplication' + - 'SpreadOperator' + - 'TooManyFunctions' + +build: + warningThreshold: 1 + failThreshold: 1 + weights: + complexity: 2 + formatting: 1 + LongParameterList: 1 + comments: 1 + +processors: + active: true + exclude: + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ClassCountProcessor' + # - 'PackageCountProcessor' + # - 'KtFileCountProcessor' + +console-reports: + active: true + exclude: + # - 'ProjectStatisticsReport' + # - 'ComplexityReport' + # - 'NotificationReport' + # - 'FindingsReport' + # - 'BuildFailureReport' + +output-reports: + active: true + exclude: + # - 'PlainOutputReport' + # - 'XmlOutputReport' + +comments: + active: true + CommentOverPrivateFunction: + active: true + CommentOverPrivateProperty: + active: true + UndocumentedPublicClass: + active: false + searchInNestedClass: false + searchInInnerClass: false + searchInInnerObject: false + searchInInnerInterface: false + UndocumentedPublicFunction: + active: false + +complexity: + active: true + LongParameterList: + active: true + threshold: 6 + ignoreDefaultParameters: true + LongMethod: + active: true + threshold: 20 + LargeClass: + active: true + threshold: 500 + ComplexInterface: + active: true + threshold: 40 + includeStaticDeclarations: false + ComplexMethod: + active: true + threshold: 40 + StringLiteralDuplication: + active: false + threshold: 2 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + MethodOverloading: + active: true + threshold: 5 + NestedBlockDepth: + active: true + threshold: 5 + TooManyFunctions: + active: true + thresholdInFiles: 20 + thresholdInClasses: 75 + thresholdInInterfaces: 40 + thresholdInObjects: 20 + thresholdInEnums: 10 + ComplexCondition: + active: true + threshold: 4 + LabeledExpression: + active: false + +empty-blocks: + active: true + EmptyCatchBlock: + active: true + EmptyClassBlock: + active: true + EmptyDefaultConstructor: + active: true + EmptyDoWhileBlock: + active: true + EmptyElseBlock: + active: true + EmptyFinallyBlock: + active: true + EmptyForBlock: + active: true + EmptyFunctionBlock: + active: true + EmptyIfBlock: + active: true + EmptyInitBlock: + active: true + EmptyKtFile: + active: true + EmptySecondaryConstructor: + active: true + EmptyWhenBlock: + active: true + EmptyWhileBlock: + active: true + +exceptions: + active: true + TooGenericExceptionCaught: + active: true + exceptions: + - ArrayIndexOutOfBoundsException + - Error + - IllegalMonitorStateException + - NullPointerException + - IndexOutOfBoundsException + - RuntimeException + - Throwable + ExceptionRaisedInUnexpectedLocation: + active: true + methodNames: 'toString,hashCode,equals,finalize' + TooGenericExceptionThrown: + active: true + exceptions: + - Error + - Exception + - NullPointerException + - Throwable + - RuntimeException + NotImplementedDeclaration: + active: true + PrintStackTrace: + active: true + InstanceOfCheckForException: + active: true + ThrowingExceptionsWithoutMessageOrCause: + active: true +# exceptions: 'IllegalArgumentException,IllegalStateException,IOException' + ReturnFromFinally: + active: true + ThrowingExceptionFromFinally: + active: true + ThrowingExceptionInMain: + active: true + RethrowCaughtException: + active: true + ThrowingNewInstanceOfSameException: + active: true + SwallowedException: + active: true + +performance: + active: true + ForEachOnRange: + active: true + SpreadOperator: + active: true + UnnecessaryTemporaryInstantiation: + active: true + +potential-bugs: + active: true + DuplicateCaseInWhenExpression: + active: true + EqualsAlwaysReturnsTrueOrFalse: + active: true + EqualsWithHashCodeExist: + active: true + IteratorNotThrowingNoSuchElementException: + active: true + IteratorHasNextCallsNextMethod: + active: true + UselessPostfixExpression: + active: true + InvalidRange: + active: true + WrongEqualsTypeParameter: + active: true + ExplicitGarbageCollectionCall: + active: true + LateinitUsage: + active: false + excludeAnnotatedProperties: "InjectPresenter, InjectExtra" + ignoreOnClassesPattern: "" + UnconditionalJumpStatementInLoop: + active: true + UnreachableCode: + active: true + UnsafeCallOnNullableType: + active: true + UnsafeCast: + active: false + +style: + active: true + CollapsibleIfStatements: + active: false + ReturnCount: + active: true + max: 3 + excludedFunctions: "equals" + ThrowsCount: + active: true + max: 2 + NewLineAtEndOfFile: + active: true + WildcardImport: + active: false + excludeImports: 'java.util.*,kotlinx.android.synthetic.*,io.apptitude.premiumparking.utils.*' + MaxLineLength: + active: true + maxLineLength: 120 + excludePackageStatements: true + excludeImportStatements: true + EqualsNullCall: + active: true + ForbiddenComment: + active: true + values: 'TODO:,FIXME:,STOPSHIP:' + ForbiddenImport: + active: true + imports: '' + FunctionOnlyReturningConstant: + active: true + ignoreOverridableFunction: true + excludedFunctions: 'describeContents' + SpacingBetweenPackageAndImports: + active: true + LoopWithTooManyJumpStatements: + active: true + maxJumpCount: 1 + MemberNameEqualsClassName: + active: true + ignoreOverriddenFunction: true + VariableNaming: + active: true + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + VariableMinLength: + active: true + minimumVariableNameLength: 3 + VariableMaxLength: + active: true + maximumVariableNameLength: 64 + TopLevelPropertyNaming: + active: true + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[a-z][A-Za-z\d]*' + privatePropertyPattern: '(_)?[a-z][A-Za-z0-9]*' + ObjectPropertyNaming: + active: true + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: true + packagePattern: '^[a-z]+(\.[a-z][a-z_0-9]*)*$' + ClassNaming: + active: true + classPattern: '[A-Z$][a-zA-Z0-9$]*' + EnumNaming: + active: true + enumEntryPattern: '^[A-Z$][a-zA-Z_$]*$' + FunctionNaming: + active: true + functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' + FunctionMaxLength: + active: true + maximumFunctionNameLength: 40 + FunctionMinLength: + active: true + minimumFunctionNameLength: 3 + ForbiddenClassName: + active: false + forbiddenName: '' + SafeCast: + active: true + UnnecessaryAbstractClass: + active: true + UnnecessaryParentheses: + active: true + UnnecessaryInheritance: + active: true + UtilityClassWithPublicConstructor: + active: true + OptionalAbstractKeyword: + active: true + OptionalWhenBraces: + active: true + OptionalReturnKeyword: + active: true + OptionalUnit: + active: true + ProtectedMemberInFinalClass: + active: true + SerialVersionUIDInSerializableClass: + active: false + MagicNumber: + active: true + ignoreNumbers: '-1,0,1,2' + ignoreHashCodeFunction: false + ignorePropertyDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + ModifierOrder: + active: true + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: 'to' + UseDataClass: + active: false + UnusedImports: + active: true + ExpressionBodySyntax: + active: true + NestedClassesVisibility: + active: true + RedundantVisibilityModifierRule: + active: true + MatchingDeclarationName: + active: true + UntilInsteadOfRangeTo: + active: true