Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Commit

Permalink
Various improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
rikvdkleij committed Jul 24, 2018
1 parent 7545bc3 commit b30befd
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ private[component] object DefinitionLocationComponent {
val qualifiedNameElement = key.qualifiedNameElement
val name = key.name
for {
sp <- ApplicationUtil.runReadActionWithWriteActionPriority(project, LineColumnPosition.fromOffset(psiFile, qualifiedNameElement.getTextRange.getStartOffset))
ep <- ApplicationUtil.runReadActionWithWriteActionPriority(project, LineColumnPosition.fromOffset(psiFile, qualifiedNameElement.getTextRange.getEndOffset))
sp <- LineColumnPosition.fromOffset(psiFile, qualifiedNameElement.getTextRange.getStartOffset)
ep <- LineColumnPosition.fromOffset(psiFile, qualifiedNameElement.getTextRange.getEndOffset)
endColumnNr = if (withoutLastColumn) ep.columnNr - 1 else ep.columnNr
repl <- StackReplsManager.getProjectRepl(psiFile)
output <- repl.findLocationInfo(key.moduleName, psiFile, sp.lineNr, sp.columnNr, ep.lineNr, endColumnNr, name)
Expand All @@ -107,12 +107,13 @@ private[component] object DefinitionLocationComponent {
val name = key.name
val (moduleName, namedElement) = output match {
case LocAtPattern(filePath, startLineNr, startColumnNr, _, _) =>
ApplicationUtil.runReadActionWithWriteActionPriority(project, HaskellReference.findIdentifierByLocation(project, filePath, startLineNr.toInt, startColumnNr.toInt, name))
val psiFile = HaskellProjectUtil.findFile(filePath, project)
HaskellReference.findIdentifierByLocation(project, psiFile, startLineNr.toInt, startColumnNr.toInt, name)
case PackageModulePattern(mn) =>
val module = HaskellProjectUtil.findModuleForFile(psiFile)
val file = HaskellReference.findFileByModuleName(project, module, mn)

(Some(mn), file.flatMap(f => ApplicationUtil.runReadActionWithWriteActionPriority(project, HaskellReference.findIdentifiersInFileByName(f, name)).headOption))
(Some(mn), file.flatMap(f => HaskellReference.findIdentifierInFileByName(f, name)))
case _ => (None, None)
}
namedElement match {
Expand Down Expand Up @@ -208,7 +209,12 @@ object LocationInfoUtil {
}

private def findNameElementsInExpression(project: Project, qualifiedNameElement: HaskellQualifiedNameElement) = {
ApplicationUtil.runReadActionWithWriteActionPriority(project, HaskellPsiUtil.findExpressionParent(qualifiedNameElement).map(HaskellPsiUtil.findQualifiedNamedElements)).getOrElse(Iterable())
val parent = ApplicationUtil.runReadAction(HaskellPsiUtil.findExpressionParent(qualifiedNameElement))
if (ApplicationUtil.runReadAction(parent.exists(_.isValid))) {
parent.map(p => ApplicationUtil.runReadAction(HaskellPsiUtil.findQualifiedNamedElements(p))).getOrElse(Iterable())
} else {
Iterable()
}
}

private def isPreloadValid(project: Project, qualifiedNameElement: HaskellQualifiedNameElement) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ class HaskellDocumentationProvider extends AbstractDocumentationProvider {
}

(moduleName, typeSignature) match {
case (Some(mn), Some(ts)) => s"""$ts $DoubleNbsp -- $mn """
case (Some(mn), None) => s"""$mn $DoubleNbsp -- No type info available""" + (if (projectFile) " (at this moment)" else "")
case (None, Some(ts)) => s"""$ts $DoubleNbsp -- No module info available (at this moment)"""
case (None, None) => "No info available (at this moment)"
case (Some(mn), Some(ts)) => s"""$DoubleNbsp $ts $DoubleNbsp -- $mn """
case (Some(mn), None) => s"""$DoubleNbsp $mn $DoubleNbsp -- No type info available""" + (if (projectFile) " (at this moment)" else "")
case (None, Some(ts)) => s"""$DoubleNbsp $ts $DoubleNbsp -- No module info available (at this moment)"""
case (None, None) => s"${DoubleNbsp}No info available (at this moment)"
}
case _ => null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import intellij.haskell.external.execution.StackCommandLine
import intellij.haskell.external.repl.StackRepl.LibType
import intellij.haskell.external.repl.StackReplsManager
import intellij.haskell.external.repl.StackReplsManager.StackComponentInfo
import intellij.haskell.util.{ApplicationUtil, HaskellFileUtil, HaskellProjectUtil}
import intellij.haskell.util.{HaskellFileUtil, HaskellProjectUtil}

import scala.collection.JavaConverters._
import scala.collection.concurrent
Expand Down Expand Up @@ -91,31 +91,31 @@ class ProjectLibraryFileWatcher(project: Project) extends BulkFileListener {

val dependentLibRepls = projectRepls.filter(repl => repl.stanzaType == LibType && dependentModules.map(_.getName).contains(repl.packageName))

val openFiles = FileEditorManager.getInstance(project).getOpenFiles.filter( HaskellFileUtil.isHaskellFile)
val openFiles = FileEditorManager.getInstance(project).getOpenFiles.filter(HaskellFileUtil.isHaskellFile)
val openProjectFiles = openFiles.filter(f => HaskellProjectUtil.isProjectFile(f, project))
val dependentFiles = openProjectFiles.filter(f => HaskellComponentsManager.findStackComponentInfo(project, HaskellFileUtil.getAbsolutePath(f)).exists(ci => ci.stanzaType != LibType && currentlyBuildComponents.map(_.packageName).contains(ci.packageName)))
val dependentLibFiles = openProjectFiles.toSeq.diff(dependentFiles.toSeq).filter(f => HaskellProjectUtil.findModuleForVirtualFile(project, f).exists(m => dependentModules.contains(m)))

(dependentRepls ++ dependentLibRepls).foreach(_.restart())

(dependentFiles ++ dependentLibFiles).foreach { vf =>
ApplicationUtil.runReadActionWithWriteActionPriority(project, HaskellFileUtil.convertToHaskellFile(project, vf)).foreach { psiFile =>
HaskellFileUtil.convertToHaskellFile(project, vf).foreach { psiFile =>
HaskellComponentsManager.invalidateLocationAndTypeInfo(psiFile)
HaskellAnnotator.restartDaemonCodeAnalyzerForFile(psiFile)
}
}
}

if (!project.isDisposed) {
val buildStatus = ProjectLibraryFileWatcher.buildStatus.get(project)
buildStatus match {
case Some(Build(componentInfos)) =>
currentlyBuildComponents = componentInfos
ProjectLibraryFileWatcher.buildStatus.put(project, Building(componentInfos))
run(progressIndicator)
case _ =>
currentlyBuildComponents = Set()
ProjectLibraryFileWatcher.buildStatus.remove(project)
}
if (!project.isDisposed) {
val buildStatus = ProjectLibraryFileWatcher.buildStatus.get(project)
buildStatus match {
case Some(Build(componentInfos)) =>
currentlyBuildComponents = componentInfos
ProjectLibraryFileWatcher.buildStatus.put(project, Building(componentInfos))
run(progressIndicator)
case _ =>
currentlyBuildComponents = Set()
ProjectLibraryFileWatcher.buildStatus.remove(project)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,12 @@ object StackProjectManager {
// Force to load the module in REPL when REPL can be started. It could have happen that IntelliJ wanted to load file (via HaskellAnnotator)
// but REPL could not be started.
FileEditorManager.getInstance(project).getSelectedFiles.find(f => HaskellProjectUtil.isProjectFile(f, project)).foreach { vf =>
ApplicationUtil.runReadActionWithWriteActionPriority(project, HaskellFileUtil.convertToHaskellFile(project, vf)).foreach(psiFile => {
HaskellFileUtil.convertToHaskellFile(project, vf).foreach(psiFile => {
if (!LoadComponent.isFileLoaded(psiFile)) {
HaskellNotificationGroup.logInfoEvent(project, s"${psiFile.getName} will be forced loaded")
HaskellAnnotator.restartDaemonCodeAnalyzerForFile(psiFile)
} else {
HaskellAnnotator.restartDaemonCodeAnalyzerForFile(psiFile)
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private[component] object TypeInfoComponent {
if (ApplicationUtil.runReadAction(element.isValid)) {
(for {
qne <- ApplicationUtil.runReadAction(HaskellPsiUtil.findQualifiedNameParent(element))
pf <- ApplicationUtil.runReadAction(Option(element.getContainingFile))
pf <- Option(element.getContainingFile)
} yield {
val moduleName = HaskellPsiUtil.findModuleName(pf)
Key(moduleName, pf, qne, qne.getName)
Expand All @@ -56,8 +56,8 @@ private[component] object TypeInfoComponent {
if (LoadComponent.isModuleLoaded(moduleName, psiFile)) {
{
for {
sp <- ApplicationUtil.runReadAction(LineColumnPosition.fromOffset(psiFile, selectionModel.getSelectionStart))
ep <- ApplicationUtil.runReadAction(LineColumnPosition.fromOffset(psiFile, selectionModel.getSelectionEnd))
sp <- LineColumnPosition.fromOffset(psiFile, selectionModel.getSelectionStart)
ep <- LineColumnPosition.fromOffset(psiFile, selectionModel.getSelectionEnd)
} yield {
StackReplsManager.getProjectRepl(psiFile).flatMap(_.findTypeInfo(moduleName, psiFile, sp.lineNr, sp.columnNr, ep.lineNr, ep.columnNr, selectionModel.getSelectedText)) match {
case Some(output) => output.stdoutLines.headOption.filterNot(_.trim.isEmpty).map(ti => Right(TypeInfo(ti, output.stderrLines.nonEmpty))).getOrElse(Left(NoInfoAvailable))
Expand Down Expand Up @@ -129,11 +129,10 @@ private[component] object TypeInfoComponent {
} else {
{
val qne = key.qualifiedNameElement
val project = key.psiFile.getProject
val to = ApplicationUtil.runReadActionWithWriteActionPriority(project, qne.getTextOffset)
val to = ApplicationUtil.runReadAction(qne.getTextOffset)
for {
sp <- ApplicationUtil.runReadActionWithWriteActionPriority(project, LineColumnPosition.fromOffset(psiFile, to))
ep <- ApplicationUtil.runReadActionWithWriteActionPriority(project, LineColumnPosition.fromOffset(psiFile, to + qne.getText.length))
sp <- LineColumnPosition.fromOffset(psiFile, to)
ep <- LineColumnPosition.fromOffset(psiFile, to + ApplicationUtil.runReadAction(qne.getText).length)
} yield {

StackReplsManager.getProjectRepl(key.psiFile).flatMap(_.findTypeInfo(key.moduleName, key.psiFile, sp.lineNr, sp.columnNr, ep.lineNr, ep.columnNr, key.expression)) match {
Expand Down
22 changes: 8 additions & 14 deletions src/main/scala/intellij/haskell/external/repl/StackRepl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@ abstract class StackRepl(project: Project, componentInfo: Option[StackComponentI
}

try {
stdoutResult.clear()
stderrResult.clear()

cleanupOutputPreviousCommand()

init()
Expand Down Expand Up @@ -196,8 +193,7 @@ abstract class StackRepl(project: Project, componentInfo: Option[StackComponentI
stdoutResult
}
Some(StackReplOutput(convertOutputToOneMessagePerLine(project, removePrompt(result)), convertOutputToOneMessagePerLine(project, stderrResult)))
}
else {
} else {
drainQueues()
logError(s"No result from Stack REPL within $timeout. Command was: $command")
exit(forceExit = true)
Expand Down Expand Up @@ -295,15 +291,13 @@ abstract class StackRepl(project: Project, componentInfo: Option[StackComponentI
}
logInfo("Stack REPL is started")
available = true
} else {
if (hasDependencyError) {
if (!ProjectLibraryFileWatcher.isBuilding(project)) {
val target = componentInfo.map(_.target).getOrElse("-")
val error = stderrQueue.asScala.headOption.map(_.replace("<command line>:", "").trim).getOrElse("a dependency failed to build")
val message = s"Stack REPL could not be started for target `$target` because $error"
logInfo(message)
HaskellEditorUtil.showStatusBarBalloonMessage(project, message)
}
} else if (hasDependencyError) {
if (!ProjectLibraryFileWatcher.isBuilding(project)) {
val target = componentInfo.map(_.target).getOrElse("-")
val error = stderrQueue.asScala.headOption.map(_.replace("<command line>:", "").trim).getOrElse("a dependency failed to build")
val message = s"Stack REPL could not be started for target `$target` because $error"
logInfo(message)
HaskellEditorUtil.showStatusBarBalloonMessage(project, message)
} else {
logError(s"Stack REPL could not be started within $DefaultTimeout")
writeOutputToLog()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ class HLintInspectionTool extends LocalInspectionTool {
private def fromOffset(psiFile: PsiFile, psiElement: PsiElement): Option[Int] = {
ProgressManager.checkCanceled()

ApplicationManager.getApplication.runReadAction(ScalaUtil.computable[Option[Int]] {
LineColumnPosition.fromOffset(psiFile, psiElement.getTextOffset).map(_.lineNr)
})
LineColumnPosition.fromOffset(psiFile, psiElement.getTextOffset).map(_.lineNr)
}

private def removeLineBreaksAndExtraSpaces(sl: Int, el: Int, s: String) = {
Expand Down
60 changes: 26 additions & 34 deletions src/main/scala/intellij/haskell/navigation/HaskellReference.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ class HaskellReference(element: HaskellNamedElement, textRange: TextRange) exten
val project = psiFile.getProject

def noNavigationMessage(noInfo: NoInfo) = {
val message = s"Navigation is not available at this moment"
val message = s"Navigation is not available at this moment" + {
noInfo match {
case ReplIsBusy => ""
case info => ": " + info.message
}
}
HaskellEditorUtil.showStatusBarBalloonMessage(project, message)
}

Expand Down Expand Up @@ -176,51 +181,36 @@ object HaskellReference {
findIdentifiersByModuleAndName(project, module, libraryNameInfo.moduleName, name)
}

def findIdentifiersByModuleAndName(project: Project, module: Option[Module], moduleName: String, name: String): Iterable[HaskellNamedElement] = {
findFileByModuleName(project, module, moduleName).map(file => {
findIdentifiersInFileByName(file, name)
}).getOrElse(Iterable())
def findIdentifiersByModuleAndName(project: Project, module: Option[Module], moduleName: String, name: String): Option[HaskellNamedElement] = {
findFileByModuleName(project, module, moduleName).flatMap(file => {
findIdentifierInFileByName(file, name)
})
}

def findIdentifiersInFileByName(file: HaskellFile, name: String): Iterable[HaskellNamedElement] = {
def findIdentifierInFileByName(file: HaskellFile, name: String): Option[HaskellNamedElement] = {
import scala.collection.JavaConverters._

ProgressManager.checkCanceled()

val topLevelExpressions = HaskellPsiUtil.findTopLevelExpressions(file)
val topLevelExpressions = ApplicationUtil.runReadAction(HaskellPsiUtil.findTopLevelExpressions(file))
val expressionIdentifiers = ApplicationUtil.runReadAction(topLevelExpressions.filterNot(_.getText.startsWith("infix")).flatMap(_.getQNameList.asScala.headOption.map(_.getIdentifierElement)).filter(_.getName == name))

ProgressManager.checkCanceled()

val topLevelIdentifiers = topLevelExpressions.flatMap(_.getQNameList.asScala.headOption.map(_.getIdentifierElement)).filter(_.getName == name)

ProgressManager.checkCanceled()
if (expressionIdentifiers.isEmpty) {
val declarationElements = ApplicationUtil.runReadAction(HaskellPsiUtil.findHaskellDeclarationElements(file))
val declarationIdentifiers = declarationElements.flatMap(_.getIdentifierElements).filter(e => ApplicationUtil.runReadAction(e.getName) == name)

val declarationElements = HaskellPsiUtil.findHaskellDeclarationElements(file)

ProgressManager.checkCanceled()
val namedElements = declarationElements.flatMap(_.getIdentifierElements).filter(_.getName == name)

ProgressManager.checkCanceled()

val identifiers = if (namedElements.isEmpty) {
HaskellPsiUtil.findHaskellDeclarationElements(file).flatMap(_.getIdentifierElements).filter(_.getName == name)
declarationIdentifiers.toSeq.sortWith(sortByClassDeclarationFirst).headOption
} else {
namedElements
expressionIdentifiers.headOption
}

topLevelIdentifiers.toSeq ++ identifiers.toSeq.sortWith(sortByClassDeclarationFirst)
}

def findIdentifierByLocation(project: Project, filePath: String, lineNr: Integer, columnNr: Integer, name: String): (Option[String], Option[HaskellNamedElement]) = {
ProgressManager.checkCanceled()
val psiFile = HaskellProjectUtil.findFile(filePath, project)
ProgressManager.checkCanceled()
def findIdentifierByLocation(project: Project, psiFile: Option[PsiFile], lineNr: Integer, columnNr: Integer, name: String): (Option[String], Option[HaskellNamedElement]) = {
val namedElement = for {
pf <- psiFile
offset <- LineColumnPosition.getOffset(pf, LineColumnPosition(lineNr, columnNr))
element <- Option(pf.findElementAt(offset))
namedElement <- HaskellPsiUtil.findNamedElement(element).find(_.getName == name).orElse(HaskellPsiUtil.findHighestDeclarationElementParent(element).flatMap(_.getIdentifierElements.find(_.getName == name))).
orElse(HaskellPsiUtil.findQualifiedNameParent(element).map(_.getIdentifierElement).find(_.getName == name))
element <- ApplicationUtil.runReadAction(Option(pf.findElementAt(offset)))
namedElement <- ApplicationUtil.runReadAction(HaskellPsiUtil.findNamedElement(element).find(_.getName == name)).
orElse(ApplicationUtil.runReadAction(HaskellPsiUtil.findHighestDeclarationElementParent(element).flatMap(_.getIdentifierElements.find(_.getName == name)))).
orElse(ApplicationUtil.runReadAction(HaskellPsiUtil.findQualifiedNameParent(element).map(_.getIdentifierElement).find(_.getName == name)))
} yield namedElement

(psiFile.flatMap(HaskellPsiUtil.findModuleName), namedElement)
Expand All @@ -243,7 +233,9 @@ object HaskellReference {

private def findIdentifiersByNameInfo(nameInfo: NameInfo, namedElement: HaskellNamedElement, project: Project): Option[HaskellNamedElement] = {
nameInfo match {
case pni: ProjectNameInfo => findIdentifierByLocation(project, pni.filePath, pni.lineNr, pni.columnNr, namedElement.getName)._2
case pni: ProjectNameInfo =>
val psiFile = HaskellProjectUtil.findFile(pni.filePath, project)
findIdentifierByLocation(project, psiFile, pni.lineNr, pni.columnNr, namedElement.getName)._2
case lni: LibraryNameInfo => findIdentifiersByLibraryNameInfo(project, HaskellProjectUtil.findModule(namedElement), lni, namedElement.getName).headOption
case _ => None
}
Expand Down
Loading

0 comments on commit b30befd

Please sign in to comment.