Workaround to give right compilation result when file is not changed but annotator is triggered.

This commit is contained in:
Rik van der Kleij 2019-04-15 20:59:27 +02:00
parent 42ddd7386b
commit 6c58cb4cb6
4 changed files with 25 additions and 22 deletions

View File

@ -30,9 +30,9 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.TreeUtil
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.{PsiElement, PsiFile}
import intellij.haskell.editor.{HaskellImportOptimizer, HaskellProblemsView}
import intellij.haskell.external.component.{StackProjectManager, _}
import intellij.haskell.external.execution._
@ -45,9 +45,9 @@ import scala.annotation.tailrec
import scala.collection.Iterable
import scala.collection.JavaConverters._
class HaskellAnnotator extends ExternalAnnotator[(PsiFile, Option[PsiElement]), CompilationResult] {
class HaskellAnnotator extends ExternalAnnotator[PsiFile, CompilationResult] {
override def collectInformation(psiFile: PsiFile, editor: Editor, hasErrors: Boolean): (PsiFile, Option[PsiElement]) = {
override def collectInformation(psiFile: PsiFile, editor: Editor, hasErrors: Boolean): PsiFile = {
if (HaskellConsoleView.isConsoleFile(psiFile) || !HaskellProjectUtil.isSourceFile(psiFile)) {
null
} else if (StackProjectManager.isInitializing(psiFile.getProject)) {
@ -61,24 +61,27 @@ class HaskellAnnotator extends ExternalAnnotator[(PsiFile, Option[PsiElement]),
case (_, None) => null // can be in case if file is in memory only (just created file)
case (_, Some(f)) if f.getFileType != HaskellFileType.Instance => null
case (_, Some(_)) if !psiFile.isValid => null
case (_, Some(_)) =>
val currentElement = Option(psiFile.findElementAt(editor.getCaretModel.getOffset)).
find(e => HaskellPsiUtil.findExpression(e).isDefined).
flatMap(e => Option(PsiTreeUtil.prevVisibleLeaf(e))).filter(_.isValid)
(psiFile, currentElement)
case (_, Some(_)) => psiFile
}
}
}
override def doAnnotate(psiFileElement: (PsiFile, Option[PsiElement])): CompilationResult = {
val psiFile = psiFileElement._1
// Workaround in case annotator is triggered but file is not changed.
// In this case the result of REPL load is always empty.
private var prevResult: Option[(PsiFile, CompilationResult)] = None
override def doAnnotate(psiFile: PsiFile): CompilationResult = {
HaskellFileUtil.findVirtualFile(psiFile) match {
case Some(virtualFile) =>
val fileChanged = FileDocumentManager.getInstance().isFileModified(virtualFile)
if (fileChanged) {
HaskellFileUtil.saveFileInDispatchThread(psiFile.getProject, virtualFile)
prevResult match {
case Some((pf, r)) if !fileChanged && psiFile == pf => r
case _ =>
HaskellFileUtil.saveFileInDispatchThread(psiFile.getProject, virtualFile)
val result = HaskellComponentsManager.loadHaskellFile(psiFile).orNull
prevResult = Some((psiFile, result))
result
}
HaskellComponentsManager.loadHaskellFile(psiFile, fileChanged, psiFileElement._2).orNull
case None => CompilationResult(Iterable(), Iterable(), failed = false)
}
}

View File

@ -131,8 +131,8 @@ object HaskellComponentsManager {
StackReplsManager.getReplsManager(project).map(_.moduleCabalInfos.map { case (_, ci) => ci }).getOrElse(Iterable())
}
def loadHaskellFile(psiFile: PsiFile, fileChanged: Boolean, psiElement: Option[PsiElement]): Option[CompilationResult] = {
LoadComponent.load(psiFile, fileChanged, psiElement)
def loadHaskellFile(psiFile: PsiFile): Option[CompilationResult] = {
LoadComponent.load(psiFile)
}
def invalidateFileInfos(psiFile: PsiFile): Unit = {

View File

@ -18,7 +18,7 @@ package intellij.haskell.external.component
import com.intellij.codeInsight.documentation.DocumentationManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.{PsiElement, PsiFile}
import com.intellij.psi.PsiFile
import intellij.haskell.external.execution.{CompilationResult, HaskellCompilationResultHelper}
import intellij.haskell.external.repl.ProjectStackRepl.Loaded
import intellij.haskell.external.repl._
@ -37,7 +37,7 @@ private[component] object LoadComponent {
}.contains(true)
}
def load(psiFile: PsiFile, fileChanged: Boolean, currentElement: Option[PsiElement]): Option[CompilationResult] = {
def load(psiFile: PsiFile): Option[CompilationResult] = {
val project = psiFile.getProject
StackReplsManager.getProjectRepl(psiFile).flatMap(projectRepl => {
@ -51,7 +51,7 @@ private[component] object LoadComponent {
ProjectLibraryFileWatcher.checkLibraryBuild(project, projectRepl.stackComponentInfo)
projectRepl.load(psiFile, Some(fileChanged)) match {
projectRepl.load(psiFile) match {
case Some((loadOutput, loadFailed)) =>
ApplicationManager.getApplication.executeOnPooledThread(ScalaUtil.runnable {

View File

@ -136,9 +136,9 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
loadedModuleNames.foreach(mn => everLoadedDependentModules.put(mn, DependentModuleInfo()))
}
def load(psiFile: PsiFile, fileChanged: Option[Boolean], mustBeByteCode: Boolean = false): Option[(StackReplOutput, Boolean)] = synchronized {
def load(psiFile: PsiFile, mustBeByteCode: Boolean = false): Option[(StackReplOutput, Boolean)] = synchronized {
val forceBytecodeLoad = if (mustBeByteCode) objectCodeEnabled else false
val reload = if (fileChanged.contains(true) && !forceBytecodeLoad) {
val reload = if (!forceBytecodeLoad) {
val loaded = isFileLoaded(psiFile)
loaded == Loaded || loaded == Failed
} else {
@ -186,7 +186,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
}
def getModuleIdentifiers(moduleName: String, psiFile: Option[PsiFile]): Option[StackReplOutput] = synchronized {
if (psiFile.isEmpty || isBrowseModuleLoaded(moduleName) || psiFile.exists(pf => load(pf, None).exists(_._2 == false))) {
if (psiFile.isEmpty || isBrowseModuleLoaded(moduleName) || psiFile.exists(pf => load(pf).exists(_._2 == false))) {
execute(s":browse! $moduleName")
} else {
HaskellNotificationGroup.logInfoEvent(project, s"Could not get module identifiers for module $moduleName because file ${psiFile.map(_.getName).getOrElse("-")} is not loaded")
@ -214,7 +214,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
case Some(info) if info.psiFile == psiFile & !info.loadFailed & (if (mustBeByteCode) !objectCodeEnabled else true) => execute(command)
case Some(info) if info.psiFile == psiFile & info.loadFailed => Some(StackReplOutput())
case _ =>
load(psiFile, fileChanged = None, mustBeByteCode)
load(psiFile, mustBeByteCode)
loadedFile match {
case None => None
case Some(info) if info.psiFile == psiFile && !info.loadFailed => execute(command)