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 @@ -127,27 +127,12 @@ fun Project.detektCustomConfig() {
args("-ex", "**/*.kts")
args("--jvm-target", "11")

val moduleDependencies = configurations
.filter { it.name == "implementation" || it.name == "api" }
.flatMap { it.dependencies.filterIsInstance<ProjectDependency>() }
.map { it.path }
.toSet()
.let {
// api configurations have canBeResolved=false, so we cannot go inside them to see transitive
// module dependencies, so including common modules
if (project.path == ":dd-sdk-android-internal") {
it
} else if (project.path == ":dd-sdk-android-core") {
it + ":dd-sdk-android-internal"
} else {
it + setOf(":dd-sdk-android-core", ":dd-sdk-android-internal")
}
}
val moduleDependencies = collectTransitiveProjectDependencies(project)

val externalDependencies = File("${projectDir.absolutePath}/detekt_classpath").readText()
val moduleDependenciesClasses = moduleDependencies.map {
val moduleDependenciesClasses = moduleDependencies.joinToString(":") {
"${rootDir.absolutePath}${it.replace(':', '/')}/build/extracted/classes.jar"
}.joinToString(":")
}

val dependencies = if (moduleDependenciesClasses.isBlank()) {
externalDependencies
Expand All @@ -158,3 +143,20 @@ fun Project.detektCustomConfig() {
args("-cp", dependencies)
}
}

private fun collectTransitiveProjectDependencies(project: Project): Set<String> {
val rootProject = project.rootProject
val visited = mutableSetOf<String>()
val queue = ArrayDeque<Project>()
queue.add(project)
while (queue.isNotEmpty()) {
val current = queue.removeFirst()
val depPaths = current.configurations
.filter { it.name == "implementation" || it.name == "api" }
.flatMap { it.dependencies.filterIsInstance<ProjectDependency>() }
.map { it.path }
.filter { visited.add(it) }
depPaths.mapNotNull { rootProject.findProject(it) }.forEach { queue.add(it) }
}
return visited
}
Original file line number Diff line number Diff line change
Expand Up @@ -390,16 +390,14 @@ class DatadogPropagationHelper internal constructor() {
val spanId = span.context().spanId.toString()
addHeader(
W3CHttpCodec.TRACE_PARENT_KEY,
// TODO RUM-11445 InvalidStringFormat false alarm
@Suppress("UnsafeThirdPartyFunctionCall", "InvalidStringFormat") // Format string is static
@Suppress("UnsafeThirdPartyFunctionCall") // Format string is static
W3C_TRACE_PARENT_DROP_SAMPLING_DECISION.format(
traceId.padStart(length = W3C_TRACE_ID_LENGTH, padChar = '0'),
spanId.padStart(length = W3C_PARENT_ID_LENGTH, padChar = '0')
)
)
// TODO RUM-2121 3rd party vendor information will be erased
// TODO RUM-11445 InvalidStringFormat false alarm
@Suppress("UnsafeThirdPartyFunctionCall", "InvalidStringFormat") // Format string is static
@Suppress("UnsafeThirdPartyFunctionCall") // Format string is static
var traceStateHeader = W3C_TRACE_STATE_DROP_SAMPLING_DECISION
.format(spanId.padStart(length = W3C_PARENT_ID_LENGTH, padChar = '0'))
if (traceOrigin != null) {
Expand Down
3 changes: 1 addition & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ kover = "0.7.6"
kspTesting = "1.5.0"

# Tools
detekt = "1.23.0"
detekt = "1.23.4"
dokka = "2.1.0"
unmock = "0.9.0"
robolectric = "4.4_r1-robolectric-r2"
Expand Down Expand Up @@ -209,7 +209,6 @@ androidLintTests = { module = "com.android.tools.lint:lint-tests", version.ref =
systemStubsJupiter = { module = "uk.org.webcompere:system-stubs-jupiter", version.ref = "systemStubsJupiter" }

# Tools
detektCli = { module = "io.gitlab.arturbosch.detekt:detekt-cli", version.ref = "detekt" }
detektApi = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" }
detektTest = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" }
okHttpMock = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okHttp" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,16 +528,14 @@ internal constructor(
val spanId = span.context().spanId.toString()
requestBuilder.addHeader(
W3C_TRACEPARENT_KEY,
// TODO RUM-11445 InvalidStringFormat false alarm
@Suppress("UnsafeThirdPartyFunctionCall", "InvalidStringFormat") // Format string is static
@Suppress("UnsafeThirdPartyFunctionCall") // Format string is static
W3C_TRACEPARENT_DROP_SAMPLING_DECISION.format(
traceId.padStart(length = W3C_TRACE_ID_LENGTH, padChar = '0'),
spanId.padStart(length = W3C_PARENT_ID_LENGTH, padChar = '0')
)
)
// TODO RUM-2121 3rd party vendor information will be erased
// TODO RUM-11445 InvalidStringFormat false alarm
@Suppress("UnsafeThirdPartyFunctionCall", "InvalidStringFormat") // Format string is static
@Suppress("UnsafeThirdPartyFunctionCall") // Format string is static
var traceStateHeader = W3C_TRACESTATE_DROP_SAMPLING_DECISION
.format(spanId.padStart(length = W3C_PARENT_ID_LENGTH, padChar = '0'))
if (traceOrigin != null) {
Expand Down
2 changes: 1 addition & 1 deletion local_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ if [[ $ANALYSIS == 1 ]]; then
detekt --config detekt_custom_general.yml,detekt_custom_safe_calls.yml,detekt_custom_unsafe_calls.yml --plugins tools/detekt/build/libs/detekt.jar -cp "$classpath" --jvm-target 11 -ex "**/*.kts"

echo "------ Detekt test pyramid rules"
rm apiSurface.log apiUsage.log
rm -f apiSurface.log apiUsage.log
detekt --config detekt_test_pyramid.yml --plugins tools/detekt/build/libs/detekt.jar -cp "$classpath" --jvm-target 11 -ex "**/*.kts"

grep -v -f apiUsage.log apiSurface.log > apiCoverageMiss.log
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
import org.jetbrains.kotlin.types.FlexibleType
import org.jetbrains.kotlin.types.lowerIfFlexible
Expand Down Expand Up @@ -53,6 +54,10 @@ internal fun Receiver.type(
type.fqNameOrNull()?.toString()
}

is PackageQualifier -> {
descriptor.fqName.asString()
}

else -> {
println("DD: Unknown receiver type ${this.javaClass}")
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -509,7 +509,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -531,7 +531,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -555,7 +555,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -580,7 +580,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -598,7 +598,7 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

@Test
Expand All @@ -616,7 +616,83 @@ internal class InvalidStringFormatTest {
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(0)
assertThat(findings).isEmpty()
}

// endregion

// region Test same-class companion object constants

@Test
fun `Ignores valid String format {same class companion object constant, ext}`() {
// Given
val code =
"""
class Foo {
companion object {
private const val PATTERN = "00-%s-%s-00"
}

fun test(a: String, b: String): String {
return PATTERN.format(a, b)
}
}
""".trimIndent()

// When
val findings = InvalidStringFormat()
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).isEmpty()
}

@Test
fun `Warns invalid argument count {same class companion object constant, ext}`() {
// Given
val code =
"""
class Foo {
companion object {
private const val PATTERN = "00-%s-%s-00"
}

fun test(a: String): String {
return PATTERN.format(a)
}
}
""".trimIndent()

// When
val findings = InvalidStringFormat()
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).hasSize(1)
}

@Test
fun `Ignores valid String format {same class companion object constant, single arg}`() {
// Given
val code =
"""
class Foo {
companion object {
private const val PATTERN = "dd=p:%s;s:0"
}

fun test(a: String): String {
return PATTERN.format(a)
}
}
""".trimIndent()

// When
val findings = InvalidStringFormat()
.compileAndLintWithContext(kotlinEnv.env, code)

// Then
assertThat(findings).isEmpty()
}

// endregion
Expand Down
Loading