mirror of
https://github.com/ilyakooo0/intellij-haskell.git
synced 2024-09-11 14:56:19 +03:00
Various improvements.
This commit is contained in:
parent
d3abf9b468
commit
47dbe78f9e
@ -20,9 +20,7 @@ import com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import intellij.haskell.external.component.{HoogleComponent, StackProjectManager}
|
||||
import intellij.haskell.util.{ApplicationUtil, HaskellEditorUtil}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import intellij.haskell.util.HaskellEditorUtil
|
||||
|
||||
class HoogleAction extends AnAction {
|
||||
|
||||
@ -38,12 +36,10 @@ class HoogleAction extends AnAction {
|
||||
|
||||
val selectionModel = actionContext.selectionModel
|
||||
selectionModel.map(_.getSelectedText).orElse(Option(psiFile.findElementAt(offset)).map(_.getText)).foreach(text => {
|
||||
ApplicationUtil.scheduleInReadActionWithWriteActionPriority(psiFile.getProject, {
|
||||
HoogleComponent.runHoogle(psiFile.getProject, text) match {
|
||||
case Some(results) => HaskellEditorUtil.showList(results, editor)
|
||||
case _ => HaskellEditorUtil.showHint(editor, s"No Hoogle result for ${StringUtil.escapeXml(text)}")
|
||||
}
|
||||
}, "hoogling", 5.seconds)
|
||||
HoogleComponent.runHoogle(psiFile.getProject, text) match {
|
||||
case Some(results) => HaskellEditorUtil.showList(results, editor)
|
||||
case _ => HaskellEditorUtil.showHint(editor, s"No Hoogle result for ${StringUtil.escapeXml(text)}")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def createLookupElement(typeSignature: String): Option[LookupElementBuilder] = {
|
||||
typeSignature.split("::", 2).toSeq match {
|
||||
case Seq(n, t) => Some(LookupElementBuilder.create(n.trim).withTypeText(StringEscapeUtils.unescapeHtml(typeSignature)))
|
||||
case Seq(n, _) => Some(LookupElementBuilder.create(n.trim).withTypeText(StringEscapeUtils.unescapeHtml(typeSignature)))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
@ -549,7 +549,7 @@ object FileModuleIdentifiers {
|
||||
} yield (f1, f2, f3)
|
||||
|
||||
try {
|
||||
val (x, y, z) = Await.result(f, 4800.milli)
|
||||
val (x, y, z) = Await.result(f, 5.seconds)
|
||||
Some(x ++ y ++ z)
|
||||
} catch {
|
||||
case _: TimeoutException =>
|
||||
@ -581,7 +581,7 @@ object HaskellCompletionContributor {
|
||||
(r1, r2)
|
||||
}
|
||||
|
||||
ScalaFutureUtil.waitWithCheckCancelled(psiFile.getProject, result, s"In useAvailableModuleIdentifiers wait for all module identifiers for ${psiFile.getName} ", 5.seconds) match {
|
||||
ScalaFutureUtil.waitWithCheckCancelled(psiFile.getProject, result, s"In useAvailableModuleIdentifiers wait for all module identifiers for ${psiFile.getName}") match {
|
||||
case Some((result1, result2)) =>
|
||||
(result1, result2) match {
|
||||
case (Some(x), Some(y)) => doIt(x, y)
|
||||
|
@ -106,6 +106,11 @@ private[component] object BrowseModuleComponent {
|
||||
Cache.synchronous().refresh(key)
|
||||
}
|
||||
|
||||
def invalidateTopLevel(project: Project, moduleName: String, psiFile: PsiFile): Unit = {
|
||||
val key = Key(project, moduleName, Some(psiFile), exported = false)
|
||||
Cache.synchronous().invalidate(key)
|
||||
}
|
||||
|
||||
def invalidateExportedModuleName(project: Project, moduleName: String): Unit = {
|
||||
val synchronousCache = Cache.synchronous
|
||||
val key = synchronousCache.asMap().keys.filter(k => k.moduleName == moduleName && k.exported) // Can be more than one for a module name if file of module can not be found
|
||||
|
@ -33,7 +33,7 @@ object HLintComponent {
|
||||
|
||||
final val HLintName = "hlint"
|
||||
private final val HLintPath = GlobalInfo.toolPath(HLintName).toString
|
||||
private final val Timeout = 1.seconds
|
||||
private final val Timeout = 1.second
|
||||
|
||||
def check(psiFile: PsiFile): Seq[HLintInfo] = {
|
||||
if (StackProjectManager.isHlintAvailable(psiFile.getProject)) {
|
||||
@ -45,7 +45,6 @@ object HLintComponent {
|
||||
case None => ()
|
||||
case Some(d) =>
|
||||
val deadline = Timeout.fromNow
|
||||
|
||||
while (isFileUnsaved(d) && deadline.hasTimeLeft() && !project.isDisposed) {
|
||||
Thread.sleep(1)
|
||||
}
|
||||
|
@ -20,16 +20,15 @@ import java.io.File
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.lang.documentation.DocumentationMarkup
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.WaitFor
|
||||
import intellij.haskell.external.execution.{CommandLine, StackCommandLine}
|
||||
import intellij.haskell.psi.{HaskellPsiUtil, HaskellQualifiedNameElement}
|
||||
import intellij.haskell.util.{HaskellProjectUtil, HtmlElement, ScalaUtil}
|
||||
import intellij.haskell.util.{HaskellProjectUtil, HtmlElement, ScalaFutureUtil}
|
||||
import intellij.haskell.{GlobalInfo, HaskellNotificationGroup}
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.concurrent.Future
|
||||
|
||||
object HoogleComponent {
|
||||
|
||||
@ -163,27 +162,12 @@ object HoogleComponent {
|
||||
}
|
||||
}
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
|
||||
private def runHoogle(project: Project, arguments: Seq[String]): Option[ProcessOutput] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val hoogleFuture = ApplicationManager.getApplication.executeOnPooledThread(ScalaUtil.callable[ProcessOutput] {
|
||||
CommandLine.run(project, HooglePath, Seq(s"--database=${hoogleDbPath(project)}") ++ arguments, logOutput = true)
|
||||
})
|
||||
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
new WaitFor(5000, 1) {
|
||||
override def condition(): Boolean = {
|
||||
ProgressManager.checkCanceled()
|
||||
hoogleFuture.isDone
|
||||
}
|
||||
}
|
||||
|
||||
if (hoogleFuture.isDone) {
|
||||
Some(hoogleFuture.get())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
ScalaFutureUtil.waitWithCheckCancelled(project, Future(CommandLine.run(project, HooglePath, Seq(s"--database=${hoogleDbPath(project)}") ++ arguments, logOutput = true)), "runHoogle")
|
||||
}
|
||||
|
||||
private def hoogleDbPath(project: Project) = {
|
||||
|
@ -76,24 +76,26 @@ private[component] object LoadComponent {
|
||||
|
||||
projectRepl.load(psiFile, Some(fileChanged)) match {
|
||||
case Some((loadOutput, loadFailed)) =>
|
||||
ApplicationManager.getApplication.executeOnPooledThread(ScalaUtil.runnable {
|
||||
if (fileChanged) {
|
||||
ApplicationManager.getApplication.executeOnPooledThread(ScalaUtil.runnable {
|
||||
|
||||
TypeInfoComponent.invalidate(psiFile)
|
||||
DefinitionLocationComponent.invalidate(psiFile)
|
||||
HaskellModuleNameIndex.invalidateNotFoundEntries(project)
|
||||
TypeInfoComponent.invalidate(psiFile)
|
||||
DefinitionLocationComponent.invalidate(psiFile)
|
||||
HaskellModuleNameIndex.invalidateNotFoundEntries(project)
|
||||
|
||||
val moduleName = HaskellPsiUtil.findModuleName(psiFile)
|
||||
if (!loadFailed) {
|
||||
NameInfoComponent.invalidate(psiFile)
|
||||
moduleName.foreach(mn => {
|
||||
BrowseModuleComponent.invalidateExportedModuleName(project, mn)
|
||||
BrowseModuleComponent.refreshTopLevel(project, mn, psiFile)
|
||||
FileModuleIdentifiers.refresh(psiFile)
|
||||
})
|
||||
val moduleName = HaskellPsiUtil.findModuleName(psiFile)
|
||||
if (!loadFailed) {
|
||||
NameInfoComponent.invalidate(psiFile)
|
||||
moduleName.foreach(mn => {
|
||||
BrowseModuleComponent.invalidateTopLevel(project, mn, psiFile)
|
||||
FileModuleIdentifiers.refresh(psiFile)
|
||||
BrowseModuleComponent.invalidateExportedModuleName(project, mn)
|
||||
})
|
||||
|
||||
}
|
||||
DocumentationManager.getInstance(project).updateToolwindowContext()
|
||||
})
|
||||
}
|
||||
DocumentationManager.getInstance(project).updateToolwindowContext()
|
||||
})
|
||||
}
|
||||
Some(HaskellCompilationResultHelper.createCompilationResult(psiFile, loadOutput.stderrLines, loadFailed))
|
||||
case _ => None
|
||||
}
|
||||
|
@ -99,9 +99,6 @@ object ProjectLibraryFileWatcher {
|
||||
|
||||
dependentRepls.foreach { repl =>
|
||||
repl.restart()
|
||||
if (repl.available && repl.stanzaType == LibType) {
|
||||
repl.load(repl.stackComponentInfo.exposedModuleNames)
|
||||
}
|
||||
}
|
||||
|
||||
// When project is opened and has build errors some REPLs could not have been started
|
||||
|
@ -91,15 +91,19 @@ private[component] object TypeInfoComponent {
|
||||
private def findTypeInfoResult(key: Key): TypeInfoResult = {
|
||||
val psiFile = key.psiFile
|
||||
val qne = key.qualifiedNameElement
|
||||
ProgressManager.checkCanceled()
|
||||
val findTypeInfo = for {
|
||||
vf <- HaskellFileUtil.findVirtualFile(psiFile)
|
||||
to = ApplicationUtil.runReadAction(qne.getTextOffset)
|
||||
sp <- LineColumnPosition.fromOffset(vf, to)
|
||||
_ = ProgressManager.checkCanceled()
|
||||
t = ApplicationUtil.runReadAction(qne.getText)
|
||||
ep <- LineColumnPosition.fromOffset(vf, to + t.length)
|
||||
t = ApplicationUtil.runReadAction(qne.getText)
|
||||
_ = ProgressManager.checkCanceled()
|
||||
mn = HaskellPsiUtil.findModuleName(psiFile)
|
||||
} yield {
|
||||
ProgressManager.checkCanceled()
|
||||
repl: ProjectStackRepl => repl.findTypeInfo(mn, key.psiFile, sp.lineNr, sp.columnNr, ep.lineNr, ep.columnNr, t)
|
||||
}
|
||||
|
||||
@ -177,8 +181,9 @@ private[component] object TypeInfoComponent {
|
||||
if (f.isCompleted) {
|
||||
Await.result(f, 1.milli)
|
||||
} else {
|
||||
HaskellNotificationGroup.logInfoEvent(key.psiFile.getProject, s"Timeout while getting type info for ${key.qualifiedNameElement.getName}")
|
||||
Left(ReadActionTimeout(s"Timeout while getting type info for ${key.qualifiedNameElement.getName}"))
|
||||
val message = s"Timeout while getting type info for ${key.qualifiedNameElement.getName}"
|
||||
HaskellNotificationGroup.logInfoEvent(key.psiFile.getProject, message)
|
||||
Left(ReadActionTimeout(message))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
|
||||
}
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
|
||||
private def isReadAccessAllowed = ApplicationManager.getApplication.isReadAccessAllowed
|
||||
|
||||
@ -79,7 +80,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
|
||||
}
|
||||
|
||||
if (isReadAccessAllowed) {
|
||||
ScalaFutureUtil.waitWithCheckCancelled(project, Future(execute), "Wait on :type-at in ProjectStackRepl").flatten
|
||||
ScalaFutureUtil.waitWithCheckCancelled(project, Future(execute), "Wait on :type-at in ProjectStackRepl", 30.seconds).flatten
|
||||
} else {
|
||||
execute
|
||||
}
|
||||
@ -93,7 +94,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
|
||||
}
|
||||
|
||||
if (isReadAccessAllowed) {
|
||||
ScalaFutureUtil.waitWithCheckCancelled(project, Future(execute), "Wait on :loc-at in ProjectStackRepl").flatten
|
||||
ScalaFutureUtil.waitWithCheckCancelled(project, Future(execute), "Wait on :loc-at in ProjectStackRepl", timeout = 30.seconds).flatten
|
||||
} else {
|
||||
execute
|
||||
}
|
||||
@ -105,7 +106,7 @@ case class ProjectStackRepl(project: Project, stackComponentInfo: StackComponent
|
||||
}
|
||||
|
||||
if (isReadAccessAllowed) {
|
||||
ScalaFutureUtil.waitWithCheckCancelled(psiFile.getProject, Future(execute), "Wait on :info in ProjectStackRepl").flatten
|
||||
ScalaFutureUtil.waitWithCheckCancelled(psiFile.getProject, Future(execute), "Wait on :info in ProjectStackRepl", 30.seconds).flatten
|
||||
} else {
|
||||
execute
|
||||
}
|
||||
|
@ -16,5 +16,4 @@ object FutureUtil {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ object ScalaFutureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
def waitWithCheckCancelled[T](project: Project, future: Future[T], actionDescription: String, timeout: FiniteDuration = 100.millis): Option[T] = {
|
||||
def waitWithCheckCancelled[T](project: Project, future: Future[T], actionDescription: String, timeout: FiniteDuration = 5.seconds): Option[T] = {
|
||||
try {
|
||||
new WaitFor(timeout.toMillis.toInt, 1) {
|
||||
override def condition(): Boolean = {
|
||||
|
Loading…
Reference in New Issue
Block a user