Repository: intellij-rust/intellij-rust
Issue: Unhandled exception in CoroutineName(DocumentationBrowser requests)

## Environment

* **IntelliJ Rust plugin version:** 0.4.169.4540-221-nightly
* **Rust toolchain version:** 1.62.0-nightly (60e50fc1c 2022-04-04) x86_64-apple-darwin
* **IDE name and version:** CLion 2022.1 Beta (CL-221.5080.93)
* **Operating system:** macOS 11.5.1
* **Macro expansion engine:** new
* **Name resolution engine:** new
* **Additional experimental features:** org.rust.cargo.features.settings.gutter, org.rust.cargo.evaluate.build.scripts, org.rust.macros.proc

## Problem description


> Unhandled exception in [CoroutineName(DocumentationBrowser requests), StandaloneCoroutine{Cancelling}@3a1fcc45, Dispatchers.Default]
> 
> java.lang.NullPointerException: getElementType(this) must not be null
> 	at org.rust.lang.core.psi.ext.PsiElementKt.getElementType(PsiElement.kt:81)
> 	at org.rust.lang.core.psi.ext.PsiElementKt.isKeywordLike(PsiElement.kt:307)
> 	at org.rust.ide.docs.RsDocumentationProvider.generateCustomDoc(RsDocumentationProvider.kt:128)
> 	at org.rust.ide.docs.RsDocumentationProvider.generateDoc(RsDocumentationProvider.kt:43)

[scratch.txt](https://github.com/intellij-rust/intellij-rust/files/8450937/scratch.txt)

<details>
    <summary>Exception</summary>


```Unhandled exception in [CoroutineName(DocumentationBrowser requests), StandaloneCoroutine{Cancelling}@3a1fcc45, Dispatchers.Default]

java.lang.NullPointerException: getElementType(this) must not be null
	at org.rust.lang.core.psi.ext.PsiElementKt.getElementType(PsiElement.kt:81)
	at org.rust.lang.core.psi.ext.PsiElementKt.isKeywordLike(PsiElement.kt:307)
	at org.rust.ide.docs.RsDocumentationProvider.generateCustomDoc(RsDocumentationProvider.kt:128)
	at org.rust.ide.docs.RsDocumentationProvider.generateDoc(RsDocumentationProvider.kt:43)
	at com.intellij.lang.documentation.CompositeDocumentationProvider.generateDoc(CompositeDocumentationProvider.java:141)
	at com.intellij.lang.documentation.psi.PsiElementDocumentationTarget.localDocHtml(PsiElementDocumentationTarget.kt:101)
	at com.intellij.lang.documentation.psi.PsiElementDocumentationTarget.localDoc(PsiElementDocumentationTarget.kt:87)
	at com.intellij.lang.documentation.psi.PsiElementDocumentationTarget.computeDocumentation(PsiElementDocumentationTarget.kt:74)
	at com.intellij.lang.documentation.impl.ImplKt$computeDocumentation$2$documentationResult$1.invoke(impl.kt:31)
	at com.intellij.lang.documentation.impl.ImplKt$computeDocumentation$2$documentationResult$1.invoke(impl.kt)
	at com.intellij.openapi.application.rw.InternalReadAction.insideReadAction(InternalReadAction.kt:96)
	at com.intellij.openapi.application.rw.InternalReadAction.access$insideReadAction(InternalReadAction.kt:13)
	at com.intellij.openapi.application.rw.InternalReadAction$tryReadCancellable$1.invoke(InternalReadAction.kt:81)
	at com.intellij.openapi.application.rw.InternalReadAction$tryReadCancellable$1.invoke(InternalReadAction.kt:13)
	at com.intellij.openapi.progress.CancellationKt$sam$com_intellij_openapi_util_ThrowableComputable$0.compute(cancellation.kt)
	at com.intellij.openapi.progress.Cancellation.withJob(Cancellation.java:60)
	at com.intellij.openapi.progress.CancellationKt.withJob(cancellation.kt:14)
	at com.intellij.openapi.progress.CancellationKt.executeWithJobAndCompleteIt(cancellation.kt:111)
	at com.intellij.openapi.application.rw.CancellableReadActionKt$cancellableReadActionInternal$2$1.run(cancellableReadAction.kt:34)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1152)
	at com.intellij.openapi.application.rw.CancellableReadActionKt$cancellableReadActionInternal$2.run(cancellableReadAction.kt:32)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runActionAndCancelBeforeWrite(ProgressIndicatorUtils.java:158)
	at com.intellij.openapi.application.rw.CancellableReadActionKt.cancellableReadActionInternal(cancellableReadAction.kt:30)
	at com.intellij.openapi.application.rw.InternalReadAction.tryReadCancellable(InternalReadAction.kt:80)
	at com.intellij.openapi.application.rw.InternalReadAction.access$tryReadCancellable(InternalReadAction.kt:13)
	at com.intellij.openapi.application.rw.InternalReadAction$tryReadAction$2.invoke(InternalReadAction.kt:66)
	at com.intellij.openapi.application.rw.InternalReadAction$tryReadAction$2.invoke(InternalReadAction.kt:13)
	at com.intellij.openapi.progress.CancellationKt$sam$com_intellij_openapi_util_ThrowableComputable$0.compute(cancellation.kt)
	at com.intellij.openapi.progress.Cancellation.withJob(Cancellation.java:60)
	at com.intellij.openapi.progress.CancellationKt.withJob(cancellation.kt:14)
	at com.intellij.openapi.progress.CoroutinesKt.blockingContext(coroutines.kt:138)
	at com.intellij.openapi.application.rw.InternalReadAction.tryReadAction(InternalReadAction.kt:61)
	at com.intellij.openapi.application.rw.InternalReadAction.readLoop(InternalReadAction.kt:53)
	at com.intellij.openapi.application.rw.InternalReadAction.access$readLoop(InternalReadAction.kt:13)
	at com.intellij.openapi.application.rw.InternalReadAction$runReadAction$4.invokeSuspend(InternalReadAction.kt:33)
	at com.intellij.openapi.application.rw.InternalReadAction$runReadAction$4.invoke(InternalReadAction.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
	at com.intellij.openapi.application.rw.InternalReadAction.runReadAction(InternalReadAction.kt:32)
	at com.intellij.openapi.application.rw.PlatformReadActionSupport.executeReadAction(PlatformReadActionSupport.kt:24)
	at com.intellij.openapi.application.CoroutinesKt.constrainedReadAction(coroutines.kt:50)
	at com.intellij.openapi.application.CoroutinesKt.readAction(coroutines.kt:20)
	at com.intellij.lang.documentation.impl.ImplKt$computeDocumentation$2.invokeSuspend(impl.kt:30)
	at com.intellij.lang.documentation.impl.ImplKt$computeDocumentation$2.invoke(impl.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
	at com.intellij.lang.documentation.impl.ImplKt.computeDocumentation(impl.kt:29)
	at com.intellij.lang.documentation.ide.impl.DocumentationPage.loadPage(DocumentationPage.kt:32)
	at com.intellij.lang.documentation.ide.impl.DocumentationBrowser.handleBrowserRequest(DocumentationBrowser.kt:92)
	at com.intellij.lang.documentation.ide.impl.DocumentationBrowser.access$handleBrowserRequest(DocumentationBrowser.kt:25)
	at com.intellij.lang.documentation.ide.impl.DocumentationBrowser$1$1.invokeSuspend(DocumentationBrowser.kt:52)
	at com.intellij.lang.documentation.ide.impl.DocumentationBrowser$1$1.invoke(DocumentationBrowser.kt)
	at kotlinx.coroutines.flow.FlowKt__MergeKt$mapLatest$1.invokeSuspend(Merge.kt:217)
	at kotlinx.coroutines.flow.FlowKt__MergeKt$mapLatest$1.invoke(Merge.kt)
	at kotlinx.coroutines.flow.FlowKt__MergeKt$mapLatest$1.invoke(Merge.kt)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$1$2.invokeSuspend(Merge.kt:34)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$1$2.invoke(Merge.kt)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$1$2.invoke(Merge.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:112)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
	at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$invokeSuspend$$inlined$collect$1.emit(Collect.kt:140)
	at kotlinx.coroutines.flow.SharedFlowImpl.collect(SharedFlow.kt:351)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3.invokeSuspend(Merge.kt:101)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3.invoke(Merge.kt)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3.invoke(Merge.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.flow.internal.FlowCoroutineKt.flowScope(FlowCoroutine.kt:33)
	at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest.flowCollect(Merge.kt:25)
	at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo$suspendImpl(ChannelFlow.kt:157)
	at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo(ChannelFlow.kt)
	at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:60)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
```

</details>


Changed files:
src/main/kotlin/org/rust/lang/core/psi/ext/PsiElement.kt, src/test/kotlin/org/rust/ide/docs/RsQuickDocumentationTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/psi/ext/PsiElement.kt b/src/main/kotlin/org/rust/lang/core/psi/ext/PsiElement.kt
index 84a24e725..a0d7e8f7a 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/ext/PsiElement.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/ext/PsiElement.kt
@@ -77,6 +77,9 @@ val PsiElement.childrenWithLeaves: Sequence<PsiElement>
  * Extracts node's element type
  */
 val PsiElement.elementType: IElementType
+    get() = elementTypeOrNull!!
+
+val PsiElement.elementTypeOrNull: IElementType?
     // XXX: be careful not to switch to AST
     get() = if (this is RsFile) RsFileStub.Type else PsiUtilCore.getElementType(this)
 
@@ -304,7 +307,7 @@ inline val <T : StubElement<*>> StubBasedPsiElement<T>.greenStub: T?
     get() = (this as? StubBasedPsiElementBase<T>)?.greenStub
 
 fun PsiElement.isKeywordLike(): Boolean {
-    return when (elementType) {
+    return when (elementTypeOrNull) {
         in RS_KEYWORDS,
         RsElementTypes.BOOL_LITERAL -> true
         RsElementTypes.IDENTIFIER -> {
diff --git a/src/test/kotlin/org/rust/ide/docs/RsQuickDocumentationTest.kt b/src/test/kotlin/org/rust/ide/docs/RsQuickDocumentationTest.kt
index 41bba8058..4bbe09e9f 100644
--- a/src/test/kotlin/org/rust/ide/docs/RsQuickDocumentationTest.kt
+++ b/src/test/kotlin/org/rust/ide/docs/RsQuickDocumentationTest.kt
@@ -1336,6 +1336,14 @@ class RsQuickDocumentationTest : RsDocumentationProviderTest() {
         <div class='content'><p>Some docs</p></div>
     """)
 
+    // https://github.com/intellij-rust/intellij-rust/issues/8732
+    fun `test do not throw exceptions on fake psi elements`() = doTest("""
+        fn main() {
+            let s = "http://localhost:8080";
+                             //^
+        }
+    """, null)
+
     private fun doTest(@Language("Rust") code: String, @Language("Html") expected: String?)
         = doTest(code, expected, block = RsDocumentationProvider::generateDoc)