Skip to content

Conversation

@alex28sh
Copy link

@alex28sh alex28sh commented May 9, 2025

Fixes for #1431

@detekt-ci detekt-ci added the rules label May 9, 2025
@detekt-ci
Copy link
Collaborator

detekt-ci commented May 9, 2025

Messages
📖 Thanks for adding a new rule to detekt ❤️
We detekted that you added tests, to your rule, that's awesome!

We detekted that you updated the default-detekt-config.yml file, that's awesome!

Generated by 🚫 dangerJS against 20ac2cc

@codecov
Copy link

codecov bot commented May 9, 2025

Codecov Report

Attention: Patch coverage is 80.76923% with 15 lines in your changes missing coverage. Please review.

Project coverage is 85.06%. Comparing base (53cae1e) to head (04a5879).

Files with missing lines Patch % Lines
.../detekt/rules/bugs/LateinitUsageInClassLevelVal.kt 80.51% 2 Missing and 13 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8125      +/-   ##
============================================
- Coverage     85.09%   85.06%   -0.03%     
- Complexity     4223     4257      +34     
============================================
  Files           575      576       +1     
  Lines         13431    13509      +78     
  Branches       2531     2557      +26     
============================================
+ Hits          11429    11492      +63     
- Misses          805      807       +2     
- Partials       1197     1210      +13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@schalkms schalkms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the amazing 1st contribution! 👍
I really like this rule. Truth to be hold, we had this rule in the backlog for a while. Great that the rule finally finds its way into the default rule set.

Sorry that it took so long to finally review the PR. Just a few comments to tidy up a bit. Afterwards, I'd say LGTM.

Comment on lines +42 to +60
// Note: The nested class test is currently skipped because the current implementation
// doesn't support detecting lateinit vars in nested classes with qualified expressions.
// This is a limitation of the current implementation and should be addressed in the future.
// @Test
// fun `reports lateinit var assigned to class-level val in nested class`() {
// val code = """
// class Outer {
// lateinit var unsafe: String
//
// class Inner {
// val someValue: String = this@Outer.unsafe
// }
// }
// """.trimIndent()
// println("[DEBUG_LOG] Nested class test code: $code")
// val findings = subject.lintWithContext(env, code)
// println("[DEBUG_LOG] Findings for nested class test: $findings")
// assertThat(findings).hasSize(1)
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to put this test code in a new issue describing the potential improvements of this rule. It's easy to overlook commented code, even so when refactoring the codebase.

}
""".trimIndent()
val findings = subject.lintWithContext(env, code)
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is conditionally initialized
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment does not provide any further value, since you already described in detail the test case intention in line 74. 👍

Suggested change
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is conditionally initialized
assertThat(findings).hasSize(1)

}
""".trimIndent()
val findings = subject.lintWithContext(env, code)
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is not initialized in all branches
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment does not provide any further value, since you already described in detail the test case intention in line 93. 👍

Suggested change
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is not initialized in all branches
assertThat(findings).hasSize(1)

}
""".trimIndent()
val findings = subject.lintWithContext(env, code)
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is not initialized in all branches
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment does not provide any further value, since you already described in detail the test case intention in line 113. 👍

Suggested change
assertThat(findings).hasSize(1) // Expecting 1 finding because the lateinit var is not initialized in all branches
assertThat(findings).hasSize(1)

}
""".trimIndent()
val findings = subject.lintWithContext(env, code)
assertThat(findings).isEmpty() // Expecting 0 findings because the lateinit var is properly initialized in all branches
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

}
""".trimIndent()
val findings = subject.lintWithContext(env, code)
assertThat(findings).isEmpty() // Expecting 0 findings because the lateinit var is properly initialized
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

import org.junit.jupiter.api.Test

@KotlinCoreEnvironmentTest
class LateinitUsageInClassLevelValSpec(val env: KotlinEnvironmentContainer) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoroughly tested! 👍

* Using a lateinit var to initialize a class-level val is problematic because the initialization
* of the val happens during object construction, while the lateinit var might be initialized later.
* This can lead to runtime exceptions or unexpected behavior.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we put a hint here that the rule currently provides the following limitation? What's your take on this?

// Note: The nested class test is currently skipped because the current implementation doesn't support detecting lateinit vars in nested classes with qualified expressions.

Comment on lines +91 to +96
val propertyDescriptor = resolvedCall.resultingDescriptor

// Check if the property is lateinit using the descriptor
// This is a brittle approach, but it's the best we can do without access to the original declaration.
// We're looking for "lateinit var" in the descriptor's string representation to be more specific.
val isLateinit = propertyDescriptor.toString().contains("lateinit var")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. Can we somehow check if the resolved call is a declaration of KtProperty or derived classes? KtProperty provides property to check for lateinit var.

Copy link
Member

@BraisGabin BraisGabin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully agree with comments from schalkms. Once addressed I would also approve this great contribution.

Really good test coverage :)

@3flex
Copy link
Member

3flex commented Jun 17, 2025

@alex28sh do you plan to update this PR to address the feedback? I haven't reviewed but based on the reviews that were done this looks like a great contribution.

Co-authored-by: Brais Gabín <braisgabin@gmail.com>
@cortinico cortinico added this to the 2.0.0 milestone Aug 30, 2025
@cortinico cortinico added the notable changes Marker for notable changes in the changelog label Aug 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

notable changes Marker for notable changes in the changelog rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants