Skip to content

MP-3345: Consider ignoring invocations and overriding of deprecated Kotlin default methods - #1560

Open
Rafał Wokacz (rawo) wants to merge 1 commit into
JetBrains:masterfrom
rawo:MP-3345-ignoring-deprecated-Kotlin-default-methods
Open

MP-3345: Consider ignoring invocations and overriding of deprecated Kotlin default methods#1560
Rafał Wokacz (rawo) wants to merge 1 commit into
JetBrains:masterfrom
rawo:MP-3345-ignoring-deprecated-Kotlin-default-methods

Conversation

@rawo

Copy link
Copy Markdown

Problem

When a Kotlin interface method is marked Daniel Edeling (@deprecated), the pre--Xjvm-default compilation strategy generates an Interface$DefaultImpls holder class for the method body, plus a compiler-generated stub in every implementing class that forwards to it. Plugin Verifier reported this compiler artifact as two false-positive warnings the plugin author never actually wrote:

  1. An invocation warning: KotlinInterface.DefaultImpls.foo(this) is deprecated but called from PluginClass
  2. An override warning: PluginClass.foo overrides deprecated fun foo()

This same class of false positive was already fixed once before for @ApiStatus.Internal/@IntellijInternalApi usages (InternalApiUsage.kt, InternalMethodOverridingProcessor.kt), but the equivalent fix was never applied to deprecation checks.

Fix

  • Added KotlinDefaultImplsUsageFilter, a new ApiUsageFilter that ignores invocations of methods owned by a synthetic $DefaultImpls class, and composed it into DeprecatedApiUsageProcessor alongside the existing SamePluginUsageFilter.
  • Fixed CompositeApiUsageFilter to forward all three allow() overloads (class-reference, method-invocation, field-access) to its child filters — it previously only forwarded the method-invocation one, which would have silently broken SamePluginUsageFilter's existing class-reference/field-access suppression once wrapped in a composite.
  • Guarded DeprecatedMethodOverridingProcessor with the existing KotlinMethods.isKotlinDefaultMethod() bytecode-pattern detector, skipping the compiler-generated stub override.
    • Deliberately did not reuse the broader hasDifferentOrigin heuristic from the internal-API fix: that check suppresses any same-origin override, not just Kotlin codegen artifacts, and would silently drop genuine same-plugin deprecated-method-override warnings — a real regression, not just theoretical (proven via a new same-plugin test fixture).
    • Known limitation, left as a documented follow-up rather than worked around: isKotlinDefaultMethod() only recognizes the pre--Xjvm-default $DefaultImpls-forwarding shape, not Kotlin 2.2+'s alternate stub shape.

Testing

  • New real-compiled Kotlin fixtures under verifier-test (DeprecatedDefaultMethodInterface, NoOverrideOfDeprecatedDefaultMethod, ExplicitOverrideOfDeprecatedDefaultMethod, SamePluginDeprecatedOverride) exercising:
    • the false-positive repro — now produces zero warnings,
    • a genuine hand-written override of the same deprecated method — still warns (proves no over-suppression),
    • a same-plugin, non-Kotlin-codegen override of a deprecated method — still warns (proves the isKotlinDefaultMethod() guard, unlike hasDifferentOrigin, doesn't regress same-origin detection).
  • New unit test DeprecatedKotlinDefaultMethodTest, pinning KotlinDefaultImplsUsageFilter and the isKotlinDefaultMethod()-based override guard against hand-built ASM bytecode, independent of the current Kotlin toolchain version.
  • Ran the full verifier-test suite and the full composite-build test task (all four modules: intellij-plugin-structure, intellij-plugin-verifier, ide-diff-builder, intellij-feature-extractor) — all green, no regressions.

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.

1 participant