Android Extensions: make synthetic import resolution more resilient

In commit ec0abb0 (Fix EA-79206: Process only valid layout.xml...) we
started to drop layouts with invalid PsiFiles during resolution of
(synthetic) package fragments.

In Android Studio we run into invalid files quite often, and it seems
to be caused by a race with some invokeLater'ed code from android-ndk;
this has the side effect of now showing all the corresponding symbols
as unresolved, and the imports themselves are suggested for removal.

As a temporary fix I propose we try again to get a valid PsiFile.

Bug: https://issuetracker.google.com/78547457
(cherry picked from commit 3e8789225bd653caaedeca7f761a6442d48214b0)
This commit is contained in:
Raluca Sauciuc
2018-06-14 17:03:02 -07:00
committed by Yan Zhulanow
parent e7c1f578d1
commit e0137ed1d5
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.android.synthetic.idea.res
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.PsiTreeChangePreprocessor
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
@@ -62,9 +63,13 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
}
override fun doExtractResources(layoutGroup: AndroidLayoutGroupData, module: ModuleDescriptor): AndroidLayoutGroup {
val layouts = layoutGroup.layouts.filter { it.isValid }.map { layout ->
val psiManager = PsiManager.getInstance(project)
val layouts = layoutGroup.layouts.map { psiFile ->
// Sometimes due to a race of later-invoked runnables, the PsiFile can be invalidated; make sure to refresh if possible,
val layout = if (psiFile.isValid) psiFile else psiManager.findFile(psiFile.virtualFile)
val resources = arrayListOf<AndroidResource>()
layout.accept(AndroidXmlVisitor { id, widgetType, attribute ->
layout?.accept(AndroidXmlVisitor { id, widgetType, attribute ->
resources += parseAndroidResource(id, widgetType, attribute.valueElement)
})
AndroidLayout(resources)