E626
Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ class RetrofitUsageDetector : Detector(), SourceCodeScanner {
return
}

val isMultipart = FQCN_MULTIPART in annotationsByFqcn
if (isMultipart && !isBodyMethod) {
node.report("@Multipart requires @PUT, @POST, or @PATCH.")
return
}

val hasPath =
(httpAnnotation.findDeclaredAttributeValue("value")?.evaluate() as? String)?.isNotBlank()
?: false

var hasBodyParam = false
var hasFieldParams = false
var hasPartParams = false
var hasUrlParam = false

for (parameter in node.uastParameters) {
Expand Down Expand Up @@ -101,6 +108,12 @@ class RetrofitUsageDetector : Detector(), SourceCodeScanner {
} else {
hasUrlParam = true
}
} else if (parameter.hasAnnotation(FQCN_PART)) {
if (!isBodyMethod) {
httpAnnotation.report("@Part param requires @PUT, @POST, or @PATCH.")
} else {
hasPartParams = true
}
}
}

Expand All @@ -112,7 +125,13 @@ class RetrofitUsageDetector : Detector(), SourceCodeScanner {
quickFixData = LintFix.create().removeNode(context, annotation.sourcePsiElement!!),
)
}
} else if (isBodyMethod && !hasBodyParam && !hasFieldParams) {
} else if (isMultipart) {
if (hasBodyParam || hasFieldParams) {
httpAnnotation.report("@Multipart methods should only contain @Part parameters.")
} else if (!hasPartParams) {
httpAnnotation.report("@Multipart methods should contain at least one @Part parameter.")
}
} else if (isBodyMethod && !hasBodyParam && !hasFieldParams && !hasPartParams) {
httpAnnotation.report("This annotation requires an `@Body` parameter.")
}
if (!hasPath && !hasUrlParam) {
Expand Down Expand Up @@ -144,7 +163,9 @@ class RetrofitUsageDetector : Detector(), SourceCodeScanner {
private val HTTP_BODY_ANNOTATIONS =
setOf("retrofit2.http.PATCH", "retrofit2.http.POST", "retrofit2.http.PUT")
private const val FQCN_FORM_ENCODED = "retrofit2.http.FormUrlEncoded"
private const val FQCN_MULTIPART = "retrofit2.http.Multipart"
private const val FQCN_FIELD = "retrofit2.http.Field"
private const val FQCN_PART = "retrofit2.http.Part"
private const val FQCN_FIELD_MAP = "retrofit2.http.FieldMap"
private const val FQCN_BODY = "retrofit2.http.Body"
private const val FQCN_URL = "retrofit2.http.Url"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class RetrofitUsageDetectorTest : BaseSlackLintTest() {

import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Multipart
import retrofit2.http.Part
import retrofit2.http.POST

interface Example {
Expand All @@ -104,6 +106,22 @@ class RetrofitUsageDetectorTest : BaseSlackLintTest() {

@POST("/")
fun correct(@Body input: String): String

@Multipart
@POST("/")
fun multipartCorrect(@Part input: String): String

@Multipart
@GET("/")
fun multipartBadMethod(@Part input: String): String

@Multipart
@POST("/")
fun multipartBadParameterType(@Body input: String): String

@Multipart
@POST("/")
fun multipartMissingPartParameter(): String
}
"""
)
Expand All @@ -112,17 +130,26 @@ class RetrofitUsageDetectorTest : BaseSlackLintTest() {
.run()
.expect(
"""
src/test/Example.kt:8: Error: @Body param requires @PUT, @POST, or @PATCH. [RetrofitUsage]
@GET("/")
~~~~~~~~~
src/test/Example.kt:11: Error: This annotation requires an @Body parameter. [RetrofitUsage]
@POST("/")
~~~~~~~~~~
src/test/Example.kt:15: Error: Duplicate @Body param!. [RetrofitUsage]
fun doubleBody(@Body input: String, @Body input2: String): String
~~~~~~~~~~~~~~~~~~~~
3 errors, 0 warnings
"""
src/test/Example.kt:10: Error: @Body param requires @PUT, @POST, or @PATCH. [RetrofitUsage]
@GET("/")
~~~~~~~~~
src/test/Example.kt:13: Error: This annotation requires an @Body parameter. [RetrofitUsage]
@POST("/")
~~~~~~~~~~
src/test/Example.kt:17: Error: Duplicate @Body param!. [RetrofitUsage]
fun doubleBody(@Body input: String, @Body input2: String): String
~~~~~~~~~~~~~~~~~~~~
src/test/Example.kt:28: Error: @Multipart requires @PUT, @POST, or @PATCH. [RetrofitUsage]
fun multipartBadMethod(@Part input: String): String
~~~~~~~~~~~~~~~~~~
src/test/Example.kt:31: Error: @Multipart methods should only contain @Part parameters. [RetrofitUsage]
@POST("/")
~~~~~~~~~~
src/test/Example.kt:35: Error: @Multipart methods should contain at least one @Part parameter. [RetrofitUsage]
@POST("/")
~~~~~~~~~~
6 errors, 0 warnings
"""
.trimIndent()
)
}
Expand Down
0