Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up Spotless #3075

Merged
merged 3 commits into from Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
}
})