Merge pull request #18 from ultrasonic/add-detekt

Add detekt
This commit is contained in:
Yahor Berdnikau 2017-07-30 22:29:45 +02:00 committed by GitHub
commit ba265b1bbe
29 changed files with 175 additions and 31 deletions

View File

@ -19,6 +19,9 @@ jobs:
- run:
name: unit-tests
command: ./gradlew test
- run:
name: static analysis
command: ./gradlew -Pqc detektCheck
- save_cache:
paths:
- ~/.gradle

View File

@ -4,18 +4,27 @@ buildscript {
repositories {
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath gradlePlugins.androidTools
classpath gradlePlugins.kotlin
classpath gradlePlugins.ktlintGradle
classpath(gradlePlugins.detekt) {
exclude module: 'kotlin-compiler-embeddable'
exclude module: 'kotlin-stdlib'
}
}
}
allprojects {
// Buildscript here is required by detekt
buildscript {
repositories {
jcenter()
}
}
repositories {
jcenter()
}

View File

@ -7,6 +7,7 @@ ext.versions = [
androidTools : "2.3.3",
ktlint : "0.9.0",
ktlintGradle : "2.1.0",
detekt : "1.0.0.M13.2",
androidSupport : "22.2.1",
@ -26,6 +27,7 @@ ext.gradlePlugins = [
androidTools : "com.android.tools.build:gradle:$versions.androidTools",
kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin",
ktlintGradle : "gradle.plugin.org.jlleitschuh.gradle:ktlint-gradle:$versions.ktlintGradle",
detekt : "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$versions.detekt",
]
ext.androidSupport = [
@ -45,7 +47,7 @@ ext.other = [
ext.testing = [
junit : "junit:junit:$versions.junit",
kotlinJunit : "org.jetbrains.kotlin:kotlin-test-junit:$versions.kotlin",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin",
mockitoKotlin : "com.nhaarman:mockito-kotlin:$versions.mockitoKotlin",
kluent : "org.amshove.kluent:kluent:$versions.kluent",
mockWebServer : "com.squareup.okhttp3:mockwebserver:$versions.okhttp",

111
detekt-config.yml Normal file
View File

@ -0,0 +1,111 @@
autoCorrect: true
failFast: false
build:
warningThreshold: 0
failThreshold: 0
weights:
complexity: 2
formatting: 1
LongParameterList: 1
comments: 1
potential-bugs:
active: true
DuplicateCaseInWhenExpression:
active: true
EqualsWithHashCodeExist:
active: true
ExplicitGarbageCollectionCall:
active: true
LateinitUsage:
active: false
UnsafeCallOnNullableType:
active: false
UnsafeCast:
active: false
performance:
active: true
ForEachOnRange:
active: true
SpreadOperator:
active: true
exceptions:
active: true
empty-blocks:
active: true
complexity:
active: true
LongMethod:
threshold: 20
LongParameterList:
threshold: 5
LargeClass:
threshold: 150
ComplexMethod:
threshold: 10
TooManyFunctions:
threshold: 10
ComplexCondition:
threshold: 3
LabeledExpression:
active: false
code-smell:
active: true
FeatureEnvy:
threshold: 0.5
weight: 0.45
base: 0.5
formatting:
active: false
style:
active: true
NewLineAtEndOfFile:
active: true
ForbiddenComment:
active: true
values: 'TODO:,FIXME:,STOPSHIP:'
WildcardImport:
active: true
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: false
excludeImportStatements: false
NamingConventionViolation:
active: true
variablePattern: '^(_)?[a-z$][a-zA-Z$0-9]*$'
constantPattern: '^([A-Z_]*|serialVersionUID)$'
methodPattern: '^[a-z\s`$][a-zA-Z\s$0-9`]*$'
classPattern: '[A-Z$][a-zA-Z$]*'
enumEntryPattern: '^[A-Z$][a-zA-Z_$0-9]*$'
comments:
active: true
CommentOverPrivateMethod:
active: true
CommentOverPrivateProperty:
active: true
UndocumentedPublicClass:
active: false
searchInNestedClass: true
searchInInnerClass: true
searchInInnerInterface: true
UndocumentedPublicFunction:
active: false
# *experimental feature*
# Migration rules can be defined in the same config file or a new one
migration:
active: false
imports:
# your.package.Class: new.package.or.Class
# for example:
# io.gitlab.arturbosch.detekt.api.Rule: io.gitlab.arturbosch.detekt.rule.Rule

View File

@ -1,10 +1,28 @@
// Applies code quality plugins when -Pqc is passed to the gradle
def isCodeQualityEnabled = project.hasProperty('qc')
// KtLint
if (isCodeQualityEnabled) {
apply plugin: "org.jlleitschuh.gradle.ktlint"
ktlint {
version = versions.ktlint
}
}
// Detekt
if (isCodeQualityEnabled) {
if (!project.rootProject.plugins.hasPlugin("io.gitlab.arturbosch.detekt")) {
Project rootProject = project.rootProject
rootProject.apply {
apply plugin: "io.gitlab.arturbosch.detekt"
detekt {
version = versions.detekt
profile("main") {
config = "${rootProject.projectDir}/detekt-config.yml"
}
}
}
}
}

View File

@ -30,6 +30,7 @@ import java.util.TimeZone
/**
* Integration test for [SubsonicAPIClient] class.
*/
@Suppress("TooManyFunctions")
class SubsonicAPIClientTest {
companion object {
const val USERNAME = "some-user"
@ -49,7 +50,7 @@ class SubsonicAPIClientTest {
}
@Test
fun `Should pass password hash and salt in query params for api version 1_13_0`() {
fun `Should pass password hash and salt in query params for api version 1 13 0`() {
val clientV12 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
PASSWORD, SubsonicAPIVersions.V1_14_0, CLIENT_ID)
enqueueResponse("ping_ok.json")
@ -70,7 +71,7 @@ class SubsonicAPIClientTest {
}
@Test
fun `Should pass hex encoded password in query params for api version 1_12_0`() {
fun `Should pass hex encoded password in query params for api version 1 12 0`() {
val clientV11 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), USERNAME,
PASSWORD, SubsonicAPIVersions.V1_12_0, CLIENT_ID)
enqueueResponse("ping_ok.json")
@ -153,7 +154,7 @@ class SubsonicAPIClientTest {
@Test
fun `Should parse get indexes ok response`() {
// TODO: check for shortcut parsing
// check for shortcut parsing
enqueueResponse("get_indexes_ok.json")
val response = client.api.getIndexes(null, null).execute()
@ -303,4 +304,4 @@ class SubsonicAPIClientTest {
version `should be` SubsonicAPIVersions.V1_13_0
error `should be` null
}
}
}

View File

@ -24,4 +24,4 @@ class MockWebServerRule : TestRule {
}
return ruleStatement
}
}
}

View File

@ -110,4 +110,4 @@ class SubsonicAPIClient(baseUrl: String,
this.addQueryParameter("s", salt)
}
}
}
}

View File

@ -30,4 +30,4 @@ interface SubsonicAPIDefinition {
@GET("getMusicDirectory.view")
fun getMusicDirectory(@Query("id") id: Long): Call<GetMusicDirectoryResponse>
}
}

View File

@ -61,4 +61,4 @@ enum class SubsonicAPIVersions(val subsonicVersions: String, val restApiVersion:
}
}
}
}
}

View File

@ -35,4 +35,4 @@ enum class SubsonicError(val code: Int) {
}
}
}
}
}

View File

@ -4,4 +4,4 @@ import java.util.Calendar
data class Artist(val id: Long,
val name: String,
val starred: Calendar?)
val starred: Calendar?)

View File

@ -4,4 +4,4 @@ import com.fasterxml.jackson.annotation.JsonProperty
data class Index(val name: String,
@JsonProperty("artist")
val artists: List<Artist>)
val artists: List<Artist>)

View File

@ -6,4 +6,4 @@ data class Indexes(val lastModified: Long,
val ignoredArticles: String?,
@JsonProperty("index")
val indexList: List<Index>,
val shortcuts: List<Index>?)
val shortcuts: List<Index>?)

View File

@ -6,4 +6,4 @@ data class License(
val valid: Boolean = false,
val email: String = "",
val trialExpires: Calendar = Calendar.getInstance(),
val licenseExpires: Calendar = Calendar.getInstance())
val licenseExpires: Calendar = Calendar.getInstance())

View File

@ -7,4 +7,4 @@ data class MusicDirectory(val id: Long,
val name: String,
val starred: Calendar?,
@JsonProperty("child")
val childList: List<MusicDirectoryChild> = emptyList())
val childList: List<MusicDirectoryChild> = emptyList())

View File

@ -6,4 +6,4 @@ data class MusicDirectoryChild(val id: Long, val parent: Long, val isDir: Boolea
val title: String = "", val album: String = "",
val artist: String = "", val year: Int?,
val genre: String = "", val coverArt: Long = -1,
val created: Calendar, val starred: Calendar?)
val created: Calendar, val starred: Calendar?)

View File

@ -1,3 +1,3 @@
package org.moire.ultrasonic.api.subsonic.models
data class MusicFolder(val id: Long = -1, val name: String = "")
data class MusicFolder(val id: Long = -1, val name: String = "")

View File

@ -8,4 +8,4 @@ class GetIndexesResponse(status: Status,
version: SubsonicAPIVersions,
error: SubsonicError?,
val indexes: Indexes?) :
SubsonicResponse(status, version, error)
SubsonicResponse(status, version, error)

View File

@ -10,4 +10,4 @@ class GetMusicDirectoryResponse(status: Status,
error: SubsonicError?,
@JsonProperty("directory")
val musicDirectory: MusicDirectory?) :
SubsonicResponse(status, version, error)
SubsonicResponse(status, version, error)

View File

@ -8,4 +8,4 @@ class LicenseResponse(val license: License = License(),
status: Status,
version: SubsonicAPIVersions,
error: SubsonicError?) :
SubsonicResponse(status, version, error)
SubsonicResponse(status, version, error)

View File

@ -30,4 +30,4 @@ class MusicFoldersResponse(status: Status,
}
}
}
}
}

View File

@ -36,4 +36,4 @@ open class SubsonicResponse(val status: Status,
}
}
}
}
}

View File

@ -41,4 +41,4 @@ class SubsonicAPIVersionsDeserializerTest {
parsedVersion `should be` SubsonicAPIVersions.V1_13_0
}
}
}

View File

@ -25,4 +25,4 @@ class SubsonicAPIVersionsTest(private val apiVersion: SubsonicAPIVersions) {
fun `Should throw IllegalArgumentException for unknown api version`() {
SubsonicAPIVersions.fromApiVersion(apiVersion.restApiVersion.substring(0, 2))
}
}
}

View File

@ -25,4 +25,4 @@ class SubsonicErrorTest(private val error: SubsonicError) {
fun `Should throw IllegalArgumentException from unknown error code`() {
SubsonicError.parseErrorFromJson(error.code + 10000)
}
}
}

View File

@ -26,4 +26,4 @@ class StatusTest(private val status: SubsonicResponse.Status) {
fun `Should throw IllegalArgumentException on unknown status`() {
SubsonicResponse.Status.getStatusFromJson(status.jsonValue.plus("-some"))
}
}
}

View File

@ -12,4 +12,4 @@ fun convertMusicFolder(entity: APIMusicFolder): MusicFolder {
fun convertMusicFolderList(entitiesList: List<APIMusicFolder>): List<MusicFolder> {
return entitiesList.map { convertMusicFolder(it) }
}
}

View File

@ -40,4 +40,4 @@ class APIConverterTest {
private fun createMusicFolder(id: Long = 0, name: String = ""): MusicFolder =
MusicFolder(id, name)
}
}