AsyncDescriptionSupplier has wrong nullability annotation

Answered

Hi, I think there is an issue with AsyncDescriptionSupplier.kt

package com.intellij.codeInsight.daemon.impl

import org.jetbrains.concurrency.Promise

interface AsyncDescriptionSupplier {
  fun requestDescription() : Promise<String>
}

The signature says it returns a Promise<String>, but when I pass a Consumer<String> into the Promise's onSuccess() method as expected by its signature, Kotlin's automatically generated assertions throw a NullPointerException because at least in Rider, the Promise can apparently return null.

Here is an example of how I'm passing the Consumer<String> into the Promise:

class Async(highlighter: RangeHighlighter, info: HighlightInfo, private val provider: AsyncDescriptionSupplier) : HighlighterWithInfo(highlighter, info) {
  fun requestDescription(callback: Consumer<String>) {
      provider.requestDescription().onSuccess(callback)
  }
}

private fun showAsynchronously(highlighterWithInfo: HighlighterWithInfo.Async) {
  highlighterWithInfo.requestDescription {
// this is a Consumer<String>, therefore "it" is a String
      // Kotlin generates an assertion to ensure "it" is not null
  }
}

And the exception that comes from Kotlin's automatically generated assertion:

java.lang.NullPointerException:
Parameter specified as non-null is null:
method com.chylex.intellij.inspectionlens.LensMarkupModelListener.showAsynchronously$lambda-2,
parameter it
    at com.chylex.intellij.inspectionlens.LensMarkupModelListener.showAsynchronously$lambda-2(LensMarkupModelListener.kt)
    at org.jetbrains.concurrency.AsyncPromise$onSuccess$1.accept(AsyncPromise.kt:84)

I assume that changing from Consumer<String> to Consumer<String?> will fix the issue, but since AsyncDescriptionSupplier is a Kotlin file I would expect it to explicitly state that requestDescription() returns a Promise<String?> to make it clear that the result can be null.

Or alternatively, if AsyncDescriptionSupplier is not supposed to return null, figure out why it is; I can't do that because the implementation is somewhere in Rider's obfuscated code.

5 comments
Comment actions Permalink

Hi Daniel,

The current requestDescription() is expected, and there shouldn't be any null returned. It sounds like an issue. I consulted a Rider developer, and they couldn't find any possibility of returning null in this place from Rider code. Maybe there is some 3rd-party plugin messing with nulls?

I suggest reproducing the error and creating an issue on Rider's issue tracker: https://youtrack.jetbrains.com/issues/RIDER

Please provide as many details as possible, including the steps to reproduce (ideally with a test project).

0
Comment actions Permalink

I have no idea how to reproduce it, I just noticed there were several exceptions because of the red (!) icon.

If it's potentially a plugin causing it, can a null check be added into the Promise so the exception points to the actual cause?

0
Comment actions Permalink

If I understand you correctly, adding a null check for values that should never be null according to defined types doesn't sound like a solution to the problem.

It still sounds like you can provide the information that can help resolve it, like the full stacktrace, IDE version, and installed plugins. We will be grateful for creating an issue on YouTrack (where you can also suggest changes) when it happens again. Thanks.

0
Comment actions Permalink

If I understand you correctly, adding a null check for values that should never be null according to defined types doesn't sound like a solution to the problem.

Kotlin automatically generates null assertions to let you know when null is passed to a non-null type, but Promise is not a Kotlin class so the non-null guarantee is broken. Placing a null assertion wherever you're receiving the result wouldn't solve the problem, it would provide a more correct stack trace.

I looked in the logs and the exceptions came while working on an Avalonia project, which has an unofficial plugin. It's possible the null came from there.

Here's the full stack trace, if you think this looks like an error in Rider then I will open an issue, otherwise it could be an issue in AvaloniaRider but I'm not sure.

2022-08-04 22:32:50,651 [47167589] SEVERE - #o.j.c.AsyncPromise - Parameter specified as non-null is null: method com.chylex.intellij.inspectionlens.LensMarkupModelListener.showAsynchronously$lambda-2, parameter it
java.lang.NullPointerException: Parameter specified as non-null is null: method com.chylex.intellij.inspectionlens.LensMarkupModelListener.showAsynchronously$lambda-2, parameter it
    at com.chylex.intellij.inspectionlens.LensMarkupModelListener.showAsynchronously$lambda-2(LensMarkupModelListener.kt)
    at org.jetbrains.concurrency.AsyncPromise$onSuccess$1.accept(AsyncPromise.kt:84)
    at org.jetbrains.concurrency.AsyncPromise$onSuccess$1.accept(AsyncPromise.kt:16)
    at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
    at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
    at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
    at org.jetbrains.concurrency.AsyncPromise.setResult(AsyncPromise.kt:146)
    at com.jetbrains.rdclient.daemon.highlighters.tooltips.FrontendAsyncTooltipHighlightInfo$tooltipCalculator$1.updateData(FrontendAsyncTooltipHighlightInfo.kt:37)
    at com.jetbrains.rdclient.daemon.highlighters.tooltips.FrontendTooltipCalculator.f(FrontendTooltipCalculator.kt:37)
    at com.jetbrains.rdclient.daemon.highlighters.tooltips.FrontendTooltipCalculator.access$applyUpdateWithRetry(FrontendTooltipCalculator.kt:8)
    at com.jetbrains.rdclient.daemon.highlighters.tooltips.FrontendTooltipCalculator$calculateTooltip$1.invoke(FrontendTooltipCalculator.kt:26)
    at com.jetbrains.rdclient.daemon.highlighters.tooltips.FrontendTooltipCalculator$calculateTooltip$1.invoke(FrontendTooltipCalculator.kt:8)
    at com.jetbrains.rd.framework.impl.RdTaskKt$startAndAdviseSuccess$1.invoke(RdTask.kt:27)
    at com.jetbrains.rd.framework.impl.RdTaskKt$startAndAdviseSuccess$1.invoke(RdTask.kt)
    at com.jetbrains.rd.util.reactive.Signal.fire(Signal.kt:32)
    at com.jetbrains.rd.util.reactive.WriteOnceProperty$WriteOnceSignal.fire(Property.kt:120)
    at com.jetbrains.rd.util.reactive.WriteOnceProperty.setIfEmpty(Property.kt:84)
    at com.jetbrains.rd.framework.impl.CallSiteWiredRdTask.onWireReceived(RdTask.kt:107)
    at com.jetbrains.rd.framework.MessageBroker$invoke$2$2.invoke(MessageBroker.kt:57)
    at com.jetbrains.rd.framework.MessageBroker$invoke$2$2.invoke(MessageBroker.kt:12)
    at com.jetbrains.rd.framework.impl.ProtocolContexts.readMessageContextAndInvoke(ProtocolContexts.kt:151)
    at com.jetbrains.rd.framework.MessageBroker$invoke$2.invoke(MessageBroker.kt:56)
    at com.jetbrains.rd.framework.MessageBroker$invoke$2.invoke(MessageBroker.kt:12)
    at com.jetbrains.rdclient.protocol.RdDispatcher.flushAll(RdDispatcher.kt:97)
    at com.jetbrains.rdclient.protocol.RdDispatcher.access$flushAll(RdDispatcher.kt:18)
    at com.jetbrains.rdclient.protocol.RdDispatcher$flushAllRunnable$1.run(RdDispatcher.kt:23)
    at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:209)
    at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:21)
    at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:191)
    at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881)
    at com.intellij.openapi.application.impl.ApplicationImpl$3.run(ApplicationImpl.java:513)
    at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:75)
    at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:118)
    at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:42)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:779)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:730)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:724)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:749)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:898)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:746)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:439)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:791)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:438)
    at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
    at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:604)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:436)
    at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:484)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
2022-08-04 22:32:50,652 [47167590] SEVERE - #o.j.c.AsyncPromise - JetBrains Rider 2022.2  Build #RD-222.3345.139
2022-08-04 22:32:50,652 [47167590] SEVERE - #o.j.c.AsyncPromise - JDK: 17.0.3; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o.
2022-08-04 22:32:50,652 [47167590] SEVERE - #o.j.c.AsyncPromise - OS: Windows 10
2022-08-04 22:32:50,652 [47167590] SEVERE - #o.j.c.AsyncPromise - Plugin to blame: Inspection Lens version: 0.0.7
0

Please sign in to leave a comment.