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

[kotlin][debugger] Introduce Kotin class metadata helper #2951

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nikita-nazarov
Copy link
Contributor

This pull requests introduces MetadataDebugHelper - a helper class that allows fetching Kotlin class metadata in the debugger.

Also, "evaluatable getters" filtering is reimplemented using the mentioned helper class. Unfortunately the new implementation of filtering is slower than the previous one that relied on bytecode inspections:

Kotlin class metadata implementation vs  Bytecode implementation

However, at the same time the new implementation allows the debugger to filter out getters like:

fun getX()
fun isX()

Which were previously shown. And show getters like:

val x: Int get() = 1

Which were previously filtered out.

Kotlin compiler stores meta information about every class in the `kotlin.Metadata` annotation. Unfortunately, there is no way to fetch this annotation using plain JDI interface, because unlike method information, class annotations are not exposed to the debugger. This commit adds a helper class that allows fetching `kotlin.Metadata` of a specific class as a JSON string.

@ApiStatus.Internal
@Service(Service.Level.PROJECT)
class KotlinMetadataDebuggerCacheService private constructor(project: Project) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it an ok implementation of a cache? Or should I use like something like this instead:

  val cache = vmProxy.getOrCreateUserData(METADATA_CACHE_KEY) {
    KotlinMetadataCache(debugProcess)
  }

Copy link
Contributor

Choose a reason for hiding this comment

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

Caching in vmProxy is better

@nikita-nazarov
Copy link
Contributor Author

@zuevmaxim

…etadata

Previously, evaluatable getters in the variables view of the Kotlin debugger relied on a filtering heuristic that inspected bytecode of each getter. Unfortunately, such filtering was incorrect in some cases. Moreover the filtering was disabled completely in the Android Studio debugger, because method bytecode is not available there. This commit reimplements filtering of evaluatable getters by using Kotlin class metadata, fetched by `MetadataDebugHelper`.
@nikita-nazarov nikita-nazarov force-pushed the nazarov/kotlin-class-metadata branch from 6845674 to 681d8bd Compare February 20, 2025 20:48
return sb.append(toJson(name)).append(':').append(value);
}

private static String toJson(String str) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it similar to com.intellij.rt.debugger.coroutines.JsonUtils#escapeJsonString?

Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure you load JsonUtils if you rely on it

.distinctBy { it.name() }
}

private fun calculateGettersToShow(methods: List<Method>, context: EvaluationContext): Set<String>? {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please use UsingMetadata suffix here also?

}
}

private fun <T> wrapJsonSyntaxException(block: () -> T): T? {
Copy link
Contributor

Choose a reason for hiding this comment

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

inline? Just because we can

Copy link
Contributor

@zuevmaxim zuevmaxim left a comment

Choose a reason for hiding this comment

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

I'll dig into details on Monday. In general, it looks great! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants