Skip to content

Commit

Permalink
Set up Spotless (arrow-kt#3075)
Browse files Browse the repository at this point in the history
  • Loading branch information
serras authored and kyay10 committed Aug 18, 2023
1 parent 96c88e0 commit 54ee578
Show file tree
Hide file tree
Showing 42 changed files with 489 additions and 359 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/pull_request.yml
Expand Up @@ -240,3 +240,30 @@ jobs:
with:
commit_message: Update API files
file_pattern: arrow-libs/**/api/*.api

spotless:
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 11

- name: spotlessApply
uses: gradle/gradle-build-action@v2
with:
arguments: spotlessApply

- name: "Commit newly formatted files"
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Apply
file_pattern: arrow-libs/**/*.kt

7 changes: 7 additions & 0 deletions arrow-libs/core/arrow-annotations/build.gradle.kts
Expand Up @@ -5,6 +5,13 @@ plugins {
alias(libs.plugins.arrowGradleConfig.kotlin)
alias(libs.plugins.arrowGradleConfig.publish)
alias(libs.plugins.arrowGradleConfig.versioning)
alias(libs.plugins.spotless)
}

spotless {
kotlin {
ktlint().editorConfigOverride(mapOf("ktlint_standard_filename" to "disabled"))
}
}

kotlin {
Expand Down
7 changes: 7 additions & 0 deletions arrow-libs/core/arrow-atomic/build.gradle.kts
Expand Up @@ -7,6 +7,13 @@ plugins {
alias(libs.plugins.arrowGradleConfig.versioning)
alias(libs.plugins.kotest.multiplatform)
alias(libs.plugins.kotlinx.kover)
alias(libs.plugins.spotless)
}

spotless {
kotlin {
ktlint().editorConfigOverride(mapOf("ktlint_standard_filename" to "disabled"))
}
}

apply(from = property("ANIMALSNIFFER_MPP"))
Expand Down
7 changes: 7 additions & 0 deletions arrow-libs/core/arrow-continuations/build.gradle.kts
Expand Up @@ -7,6 +7,13 @@ plugins {
alias(libs.plugins.arrowGradleConfig.versioning)
alias(libs.plugins.kotlinx.kover)
alias(libs.plugins.kotest.multiplatform)
alias(libs.plugins.spotless)
}

spotless {
kotlin {
ktlint().editorConfigOverride(mapOf("ktlint_standard_filename" to "disabled"))
}
}

apply(from = property("ANIMALSNIFFER_MPP"))
Expand Down
7 changes: 7 additions & 0 deletions arrow-libs/core/arrow-core-retrofit/build.gradle.kts
Expand Up @@ -6,6 +6,13 @@ plugins {
alias(libs.plugins.arrowGradleConfig.publish)
alias(libs.plugins.kotlinx.serialization) // Needed for testing only
alias(libs.plugins.kotlinx.kover)
alias(libs.plugins.spotless)
}

spotless {
kotlin {
ktlint().editorConfigOverride(mapOf("ktlint_standard_filename" to "disabled"))
}
}

apply(from = property("ANIMALSNIFFER"))
Expand Down
Expand Up @@ -17,7 +17,7 @@ import java.lang.reflect.Type
internal class ArrowEitherCallAdapter<E, R>(
retrofit: Retrofit,
errorType: Type,
private val bodyType: Type
private val bodyType: Type,
) : CallAdapter<R, Call<Either<E, R>>> {

private val errorConverter: Converter<ResponseBody, E> =
Expand All @@ -30,7 +30,7 @@ internal class ArrowEitherCallAdapter<E, R>(
class EitherCall<E, R>(
private val original: Call<R>,
private val errorConverter: Converter<ResponseBody, E>,
private val bodyType: Type
private val bodyType: Type,
) : Call<Either<E, R>> {

override fun enqueue(callback: Callback<Either<E, R>>) {
Expand All @@ -52,7 +52,7 @@ internal class ArrowEitherCallAdapter<E, R>(
},
{ errorBody, _ ->
Response.success(errorBody.left())
}
},
)
}
})
Expand Down
Expand Up @@ -16,7 +16,7 @@ import java.lang.reflect.Type
internal class ArrowResponseECallAdapter<E, R>(
retrofit: Retrofit,
errorType: Type,
private val bodyType: Type
private val bodyType: Type,
) : CallAdapter<R, Call<ResponseE<E, R>>> {

private val errorConverter: Converter<ResponseBody, E> =
Expand All @@ -29,7 +29,7 @@ internal class ArrowResponseECallAdapter<E, R>(
class ResponseECall<E, R>(
private val original: Call<R>,
private val errorConverter: Converter<ResponseBody, E>,
private val bodyType: Type
private val bodyType: Type,
) : Call<ResponseE<E, R>> {

override fun enqueue(callback: Callback<ResponseE<E, R>>) {
Expand All @@ -51,7 +51,7 @@ internal class ArrowResponseECallAdapter<E, R>(
},
{ errorBody, responseV ->
Response.success(ResponseE(responseV.raw(), errorBody.left()))
}
},
)
}
})
Expand Down
Expand Up @@ -78,7 +78,7 @@ public class EitherCallAdapterFactory : CallAdapter.Factory() {
val name = parseTypeName(returnType)
throw IllegalArgumentException(
"Return type must be parameterized as " +
"$name<Foo> or $name<out Foo>"
"$name<Foo> or $name<out Foo>",
)
}

Expand All @@ -90,16 +90,17 @@ public class EitherCallAdapterFactory : CallAdapter.Factory() {

private fun eitherAdapter(
returnType: ParameterizedType,
retrofit: Retrofit
retrofit: Retrofit,
): CallAdapter<Type, out Call<out Any>>? {
val wrapperType = getParameterUpperBound(0, returnType)
return when (getRawType(wrapperType)) {
Either::class.java -> {
val (errorType, bodyType) = extractErrorAndReturnType(wrapperType, returnType)
if (errorType == CallError::class.java)
if (errorType == CallError::class.java) {
NetworkEitherCallAdapter(bodyType)
else
} else {
ArrowEitherCallAdapter<Any, Type>(retrofit, errorType, bodyType)
}
}
ResponseE::class.java -> {
val (errorType, bodyType) = extractErrorAndReturnType(wrapperType, returnType)
Expand All @@ -114,7 +115,7 @@ public class EitherCallAdapterFactory : CallAdapter.Factory() {
val name = parseTypeName(returnType)
throw IllegalArgumentException(
"Return type must be parameterized as " +
"$name<ErrorBody, ResponseBody> or $name<out ErrorBody, out ResponseBody>"
"$name<ErrorBody, ResponseBody> or $name<out ErrorBody, out ResponseBody>",
)
}
val errorType = getParameterUpperBound(0, wrapperType)
Expand Down
Expand Up @@ -6,7 +6,7 @@ import okhttp3.Response

public data class ResponseE<E, A>(
val raw: Response,
val body: Either<E, A>
val body: Either<E, A>,
) {

val code: Int = raw.code()
Expand Down
Expand Up @@ -14,7 +14,7 @@ internal inline fun <E, R, T> onResponseFn(
bodyType: Type,
response: Response<R>,
newResponseFn: (R, Response<R>) -> Response<T>,
errorResponseFn: (E, Response<R>) -> Response<T>
errorResponseFn: (E, Response<R>) -> Response<T>,
) {
if (response.isSuccessful) {
val body = response.body()
Expand Down
Expand Up @@ -13,7 +13,7 @@ public sealed class CallError
public data class HttpError(
val code: Int,
val message: String,
val body: String
val body: String,
) : CallError()

/**
Expand Down
Expand Up @@ -13,7 +13,7 @@ import java.io.IOException
import java.lang.reflect.Type

internal class NetworkEitherCallAdapter<R>(
private val successType: Type
private val successType: Type,
) : CallAdapter<R, Call<Either<CallError, R?>>> {

override fun adapt(call: Call<R?>): Call<Either<CallError, R?>> = EitherCall(call, successType)
Expand All @@ -23,7 +23,7 @@ internal class NetworkEitherCallAdapter<R>(

private class EitherCall<R>(
private val delegate: Call<R>,
private val successType: Type
private val successType: Type,
) : Call<Either<CallError, R>> {

override fun enqueue(callback: Callback<Either<CallError, R>>) = delegate.enqueue(
Expand All @@ -40,7 +40,7 @@ private class EitherCall<R>(
return HttpError(
code = code(),
message = message(),
body = errorBody
body = errorBody,
).left()
}

Expand All @@ -57,8 +57,8 @@ private class EitherCall<R>(
IllegalStateException(
"Response code is ${code()} but body is null.\n" +
"If you expect response body to be null then define your API method as returning Unit:\n" +
"@POST fun postSomething(): Either<CallError, Unit>"
)
"@POST fun postSomething(): Either<CallError, Unit>",
),
).left()
}
}
Expand All @@ -71,7 +71,7 @@ private class EitherCall<R>(
}
callback.onResponse(this@EitherCall, Response.success(error.left()))
}
}
},
)

override fun timeout(): Timeout = delegate.timeout()
Expand Down
Expand Up @@ -18,73 +18,72 @@ class ArrowEitherCallAdapterTest : StringSpec({
lateinit var server: MockWebServer
lateinit var service: SuspendApiTestClient

beforeAny {
server = MockWebServer()
server.start()
service = Retrofit.Builder()
.baseUrl(server.url("/"))
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(EitherCallAdapterFactory.create())
.build()
.create(SuspendApiTestClient::class.java)
}
beforeAny {
server = MockWebServer()
server.start()
service = Retrofit.Builder()
.baseUrl(server.url("/"))
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(EitherCallAdapterFactory.create())
.build()
.create(SuspendApiTestClient::class.java)
}

afterAny { server.shutdown() }
afterAny { server.shutdown() }

"should return ResponseMock for 200 with valid JSON" {
server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))
"should return ResponseMock for 200 with valid JSON" {
server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))

val body = service.getEither()
val body = service.getEither()

body shouldBe ResponseMock("Arrow rocks").right()
}
body shouldBe ResponseMock("Arrow rocks").right()
}

"should return Unit when service method returns Unit and null body received" {
server.enqueue(MockResponse().setResponseCode(204))
"should return Unit when service method returns Unit and null body received" {
server.enqueue(MockResponse().setResponseCode(204))

val body = service.postSomething("Sample string")
val body = service.postSomething("Sample string")

body shouldBe Unit.right()
}
body shouldBe Unit.right()
}

"should return Unit when service method returns Unit and JSON body received" {
server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))
"should return Unit when service method returns Unit and JSON body received" {
server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))

val body = service.postSomething("Sample string")
val body = service.postSomething("Sample string")

body shouldBe Unit.right()
}
body shouldBe Unit.right()
}

"should return ErrorMock for 400 with valid JSON" {
server.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400))
"should return ErrorMock for 400 with valid JSON" {
server.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400))

val body = service.getEither()
val body = service.getEither()

body shouldBe ErrorMock(666).left()
}
body shouldBe ErrorMock(666).left()
}

"should throw for 200 with invalid JSON" {
server.enqueue(MockResponse().setBody("""not a valid JSON"""))
"should throw for 200 with invalid JSON" {
server.enqueue(MockResponse().setBody("""not a valid JSON"""))

val body = runCatching { service.getEither() }
val body = runCatching { service.getEither() }

body.isFailure shouldBe true
}
body.isFailure shouldBe true
}

"should throw for 400 and invalid JSON" {
server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400))
"should throw for 400 and invalid JSON" {
server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400))

val body = runCatching { service.getEither() }
val body = runCatching { service.getEither() }

body.isFailure shouldBe true
}
body.isFailure shouldBe true
}

"should throw when server disconnects" {
server.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AFTER_REQUEST })
"should throw when server disconnects" {
server.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AFTER_REQUEST })

val body = runCatching { service.getEither() }

body.isFailure shouldBe true
}
val body = runCatching { service.getEither() }

body.isFailure shouldBe true
}
})

0 comments on commit 54ee578

Please sign in to comment.