mirror of
https://github.com/ilyakooo0/intellij-haskell.git
synced 2024-09-11 14:56:19 +03:00
Improved finding references in library code.
This commit is contained in:
parent
427fe7e95e
commit
bce9451c18
@ -125,8 +125,8 @@ private[component] object DefinitionLocationComponent {
|
||||
if (libraryFile || key.importQualifier.isDefined || key.qualifiedNameElement.getQualifierName.isDefined) {
|
||||
|
||||
findLocationByImportedIdentifiers(project, key, name) match {
|
||||
case Some(r) => r
|
||||
case None => if (libraryFile) {
|
||||
case r@Right(_) => r
|
||||
case Left(_) => if (libraryFile) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
HaskellComponentsManager.findNameInfo(key.qualifiedNameElement) match {
|
||||
@ -135,7 +135,7 @@ private[component] object DefinitionLocationComponent {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
HaskellReference.findIdentifiersByNameInfo(info, key.qualifiedNameElement.getIdentifierElement, project) match {
|
||||
case Right(nes) if nes.nonEmpty => nes.headOption.map(ne => Right(PackageModuleLocation(findModuleName(ne), ne, name))).getOrElse(Left(NoInfoAvailable(name, psiFile.getName)))
|
||||
case Right((mn, ne)) => Right(PackageModuleLocation(findModuleName(ne), ne, name))
|
||||
case Left(noInfo) =>
|
||||
HaskellReference.findIdentifierInFileByName(psiFile, name).
|
||||
map(ne => Right(PackageModuleLocation(findModuleName(ne), ne, name))).getOrElse(Left(noInfo))
|
||||
@ -158,7 +158,7 @@ private[component] object DefinitionLocationComponent {
|
||||
val withoutLastColumn = name.headOption.exists(_.isUpper)
|
||||
findLocationByRepl(project, psiFile, moduleName, key, name, withoutLastColumn) match {
|
||||
case r@Right(_) => r
|
||||
case Left(_) => findLocationByImportedIdentifiers(project, key, name).getOrElse(Left(NoInfoAvailable(name, key.psiFile.getName)))
|
||||
case Left(_) => findLocationByImportedIdentifiers(project, key, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,25 +167,24 @@ private[component] object DefinitionLocationComponent {
|
||||
Option(namedElement.getContainingFile).flatMap(HaskellPsiUtil.findModuleName).getOrElse("-")
|
||||
}
|
||||
|
||||
private def findLocationByImportedIdentifiers(project: Project, key: Key, name: String): Option[DefinitionLocationResult] = {
|
||||
val psiFile = key.psiFile
|
||||
val mids = FileModuleIdentifiers.findAvailableModuleIdentifiers(psiFile)
|
||||
|
||||
private def findLocationByImportedIdentifiers(project: Project, key: Key, name: String): Either[NoInfo, PackageModuleLocation] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val psiFile = key.psiFile
|
||||
|
||||
val qNameName = key.qualifiedNameElement.getName
|
||||
val qName = key.importQualifier match {
|
||||
case None => qNameName
|
||||
case Some(q) => q + "." + qNameName
|
||||
}
|
||||
|
||||
for {
|
||||
mid <- mids.find(_.name == qName)
|
||||
} yield {
|
||||
HaskellReference.findIdentifiersByModuleAndName(project, Seq(mid.moduleName), name) match {
|
||||
case Right(nes) if nes.nonEmpty => nes.headOption.map(ne => Right(PackageModuleLocation(mid.moduleName, ne, name, Some(qName)))).getOrElse(Left(NoInfoAvailable(name, psiFile.getName)))
|
||||
case _ => Left(NoInfoAvailable(name, psiFile.getName))
|
||||
}
|
||||
val moduleNames = FileModuleIdentifiers.findAvailableModuleIdentifiers(psiFile).filter(_.name == qName).map(_.moduleName).toSeq
|
||||
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
HaskellReference.findIdentifiersByModulesAndName(project, moduleNames, name) match {
|
||||
case Right((mn, ne)) => Right(PackageModuleLocation(mn, ne, name))
|
||||
case Left(noInfo) => Left(noInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,11 +267,9 @@ sealed trait DefinitionLocation {
|
||||
def namedElement: HaskellNamedElement
|
||||
|
||||
def originalName: String
|
||||
|
||||
def originalQualifiedName: Option[String]
|
||||
}
|
||||
|
||||
case class PackageModuleLocation(moduleName: String, namedElement: HaskellNamedElement, originalName: String, originalQualifiedName: Option[String] = None) extends DefinitionLocation
|
||||
case class PackageModuleLocation(moduleName: String, namedElement: HaskellNamedElement, originalName: String) extends DefinitionLocation
|
||||
|
||||
case class LocalModuleLocation(psiFile: PsiFile, namedElement: HaskellNamedElement, originalName: String, originalQualifiedName: Option[String] = None) extends DefinitionLocation
|
||||
case class LocalModuleLocation(psiFile: PsiFile, namedElement: HaskellNamedElement, originalName: String) extends DefinitionLocation
|
||||
|
||||
|
@ -128,8 +128,8 @@ object FileModuleIdentifiers {
|
||||
}
|
||||
}
|
||||
|
||||
private def getModuleIdentifiersFromFullImportedModules(impliciPrelueActive: Boolean, psiFile: PsiFile, importDeclarations: Iterable[HaskellImportDeclaration]): Future[Iterable[Option[Iterable[ModuleIdentifier]]]] = {
|
||||
val importInfos = getFullImportedModules(impliciPrelueActive, psiFile, importDeclarations)
|
||||
private def getModuleIdentifiersFromFullImportedModules(noImplicitPrelude: Boolean, psiFile: PsiFile, importDeclarations: Iterable[HaskellImportDeclaration]): Future[Iterable[Option[Iterable[ModuleIdentifier]]]] = {
|
||||
val importInfos = getFullImportedModules(noImplicitPrelude, psiFile, importDeclarations)
|
||||
|
||||
Future.sequence(importInfos.map(importInfo => {
|
||||
val allModuleIdentifiers = HaskellComponentsManager.findModuleIdentifiers(psiFile.getProject, importInfo.moduleName)
|
||||
@ -173,14 +173,14 @@ object FileModuleIdentifiers {
|
||||
info.isImplicitPreludeActive || ApplicationUtil.runReadAction(HaskellPsiUtil.findLanguageExtensions(psiFile)).exists(p => ApplicationUtil.runReadAction(p.getText).contains("NoImplicitPrelude"))
|
||||
}
|
||||
|
||||
private def getFullImportedModules(implicitPreludeActive: Boolean, psiFile: PsiFile, importDeclarations: Iterable[HaskellImportDeclaration]): Iterable[ImportFull] = {
|
||||
private def getFullImportedModules(noImplicitPrelude: Boolean, psiFile: PsiFile, importDeclarations: Iterable[HaskellImportDeclaration]): Iterable[ImportFull] = {
|
||||
val moduleNames = for {
|
||||
id <- importDeclarations
|
||||
if Option(id.getImportSpec).isEmpty
|
||||
mn <- ApplicationUtil.runReadAction(id.getModuleName)
|
||||
} yield ImportFull(mn, Option(id.getImportQualified).isDefined, Option(id.getImportQualifiedAs).map(qa => ApplicationUtil.runReadAction(qa.getQualifier.getName)))
|
||||
|
||||
if (moduleNames.map(_.moduleName).toSeq.contains(HaskellProjectUtil.Prelude) || implicitPreludeActive) {
|
||||
if (moduleNames.map(_.moduleName).toSeq.contains(HaskellProjectUtil.Prelude) || noImplicitPrelude) {
|
||||
moduleNames
|
||||
} else {
|
||||
Iterable(ImportFull(HaskellProjectUtil.Prelude, qualified = false, None)) ++ moduleNames
|
||||
|
@ -68,8 +68,8 @@ object HoogleComponent {
|
||||
None
|
||||
case Right(info) =>
|
||||
val moduleName = info match {
|
||||
case PackageModuleLocation(mn, _, _, _) => Some(mn)
|
||||
case LocalModuleLocation(pf, _, _, _) => HaskellPsiUtil.findModuleName(pf)
|
||||
case PackageModuleLocation(mn, _, _) => Some(mn)
|
||||
case LocalModuleLocation(pf, _, _) => HaskellPsiUtil.findModuleName(pf)
|
||||
}
|
||||
moduleName match {
|
||||
case None =>
|
||||
|
@ -167,8 +167,8 @@ class HaskellReference(element: HaskellNamedElement, textRange: TextRange) exten
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
HaskellComponentsManager.findDefinitionLocation(psiFile, qualifiedNameElement, importQualifier) match {
|
||||
case Right(PackageModuleLocation(_, ne, _, _)) => Right(ne)
|
||||
case Right(LocalModuleLocation(_, ne, _, _)) => Right(ne)
|
||||
case Right(PackageModuleLocation(_, ne, _)) => Right(ne)
|
||||
case Right(LocalModuleLocation(_, ne, _)) => Right(ne)
|
||||
case Left(noInfo) => Left(noInfo)
|
||||
}
|
||||
}
|
||||
@ -178,12 +178,10 @@ class HaskellReference(element: HaskellNamedElement, textRange: TextRange) exten
|
||||
}
|
||||
|
||||
private def findHaskellFile(importDeclarations: Iterable[HaskellImportDeclaration], qualifierElement: HaskellNamedElement, project: Project): Either[NoInfo, Option[PsiFile]] = {
|
||||
val result = for {
|
||||
id <- importDeclarations.find(id => id.getModuleName.contains(qualifierElement.getName))
|
||||
(for {
|
||||
id <- importDeclarations.find(_.getModuleName.contains(qualifierElement.getName))
|
||||
mn <- id.getModuleName
|
||||
} yield HaskellModuleNameIndex.findFilesByModuleName(project, mn)
|
||||
|
||||
result match {
|
||||
} yield HaskellModuleNameIndex.findFilesByModuleName(project, mn)) match {
|
||||
case Some(Right(files)) => Right(files.headOption)
|
||||
case Some(Left(noInfo)) => Left(noInfo)
|
||||
case None => Right(None)
|
||||
@ -199,34 +197,48 @@ object HaskellReference {
|
||||
HaskellEditorUtil.showStatusBarBalloonMessage(project, "Navigating to instance declarations is not available at this moment")
|
||||
Seq()
|
||||
} else {
|
||||
identifiers.flatMap(_.toOption).flatten
|
||||
identifiers.flatMap(_.toOption.map(_._2))
|
||||
}
|
||||
}
|
||||
|
||||
def findIdentifiersByLibraryNameInfo(project: Project, libraryNameInfo: LibraryNameInfo, name: String): Either[NoInfo, Seq[HaskellNamedElement]] = {
|
||||
findIdentifiersByModuleAndName(project, Seq(libraryNameInfo.moduleName), name)
|
||||
def findIdentifiersByLibraryNameInfo(project: Project, libraryNameInfo: LibraryNameInfo, name: String): Either[NoInfo, (String, HaskellNamedElement)] = {
|
||||
findIdentifiersByModuleAndName(project, libraryNameInfo.moduleName, name)
|
||||
}
|
||||
|
||||
def findIdentifiersByModuleAndName(project: Project, moduleNames: Seq[String], name: String): Either[NoInfo, Seq[HaskellNamedElement]] = {
|
||||
def findIdentifiersByModuleAndName(project: Project, moduleName: String, name: String): Either[NoInfo, (String, HaskellNamedElement)] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
moduleNames.map(mn => HaskellModuleNameIndex.findFilesByModuleName(project, mn)).find(_.isLeft) match {
|
||||
case Some(Left(noInfo)) => Left(noInfo)
|
||||
case _ =>
|
||||
findIdentifiersByModulesAndName(project, Seq(moduleName), name)
|
||||
}
|
||||
|
||||
def findIdentifiersByModulesAndName(project: Project, moduleNames: Seq[String], name: String): Either[NoInfo, (String, HaskellNamedElement)] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
findIdentifiersByModuleAndName2(project, moduleNames, name).headOption.map {
|
||||
case (mn, nes) => nes.headOption.map(ne => Right((mn, ne))).getOrElse(Left(NoInfoAvailable(name, moduleNames.mkString(" | "))))
|
||||
}.getOrElse(Left(ModuleNotAvailable(moduleNames.mkString(" | "))))
|
||||
}
|
||||
|
||||
private def findIdentifiersByModuleAndName2(project: Project, moduleNames: Seq[String], name: String): Seq[(String, Seq[HaskellNamedElement])] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
moduleNames.distinct.flatMap(mn => HaskellModuleNameIndex.findFilesByModuleName(project, mn) match {
|
||||
case Left(_) => Seq()
|
||||
case Right(files) =>
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val identifiers = moduleNames.map(mn => HaskellModuleNameIndex.findFilesByModuleName(project, mn)).flatMap(_.toSeq.flatMap(_.flatMap(f => findIdentifierInFileByName(f, name))))
|
||||
val identifiers = files.flatMap(f => findIdentifierInFileByName(f, name))
|
||||
if (identifiers.isEmpty) {
|
||||
val importedModuleNames = moduleNames.map(mn => HaskellModuleNameIndex.findFilesByModuleName(project, mn)).flatMap(_.toSeq.flatMap(_.flatMap(pf => HaskellPsiUtil.findImportDeclarations(pf).flatMap(_.getModuleName))))
|
||||
val importedModuleNames = files.flatMap(f => FileModuleIdentifiers.findAvailableModuleIdentifiers(f).filter(_.name == name).map(_.moduleName))
|
||||
if (importedModuleNames.isEmpty) {
|
||||
Right(Seq())
|
||||
Seq()
|
||||
} else {
|
||||
findIdentifiersByModuleAndName(project, importedModuleNames, name)
|
||||
findIdentifiersByModuleAndName2(project, importedModuleNames, name)
|
||||
}
|
||||
} else {
|
||||
Right(identifiers)
|
||||
Seq((mn, identifiers))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def findIdentifierInFileByName(psifile: PsiFile, name: String): Option[HaskellNamedElement] = {
|
||||
@ -291,7 +303,7 @@ object HaskellReference {
|
||||
}
|
||||
}
|
||||
|
||||
def findIdentifiersByNameInfo(nameInfo: NameInfo, namedElement: HaskellNamedElement, project: Project): Either[NoInfo, Seq[HaskellNamedElement]] = {
|
||||
def findIdentifiersByNameInfo(nameInfo: NameInfo, namedElement: HaskellNamedElement, project: Project): Either[NoInfo, (Option[String], HaskellNamedElement)] = {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val name = namedElement.getName
|
||||
@ -300,11 +312,11 @@ object HaskellReference {
|
||||
val (virtualFile, psiFile) = HaskellFileUtil.findFileInRead(project, pni.filePath)
|
||||
ProgressManager.checkCanceled()
|
||||
(virtualFile, psiFile) match {
|
||||
case (Some(vf), Right(pf)) => findIdentifierByLocation(project, vf, pf, pni.lineNr, pni.columnNr, name).map(r => Right(Seq(r))).getOrElse(Left(NoInfoAvailable(name, "-")))
|
||||
case (Some(vf), Right(pf)) => findIdentifierByLocation(project, vf, pf, pni.lineNr, pni.columnNr, name).map(r => Right(HaskellPsiUtil.findModuleName(pf), r)).getOrElse(Left(NoInfoAvailable(name, "-")))
|
||||
case (_, Right(_)) => Left(NoInfoAvailable(name, "-"))
|
||||
case (_, Left(noInfo)) => Left(noInfo)
|
||||
}
|
||||
case lni: LibraryNameInfo => findIdentifiersByLibraryNameInfo(project, lni, name)
|
||||
case lni: LibraryNameInfo => findIdentifiersByLibraryNameInfo(project, lni, name).map({ case (mn, nes) => (Some(mn), nes) })
|
||||
case _ => Left(NoInfoAvailable(name, "-"))
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ class HoogleByNameContributor extends ChooseByNameContributor {
|
||||
val result = HaskellComponentsManager.findNameInfoByModuleName(project, moduleName, name)
|
||||
ProgressManager.checkCanceled()
|
||||
val navigationItemByNameInfo = result.toOption.flatMap(_.headOption) match {
|
||||
case Some(lni: LibraryNameInfo) => HaskellReference.findIdentifiersByLibraryNameInfo(project, lni, name).toOption.getOrElse(Seq()).
|
||||
flatMap(HaskellPsiUtil.findDeclarationElement).map(d => createLibraryNavigationItem(d, moduleName))
|
||||
case Some(lni: LibraryNameInfo) => HaskellReference.findIdentifiersByLibraryNameInfo(project, lni, name).toOption.
|
||||
flatMap(x => HaskellPsiUtil.findDeclarationElement(x._2)).map(d => createLibraryNavigationItem(d, moduleName)).toSeq
|
||||
case Some(pni: ProjectNameInfo) =>
|
||||
HaskellFileUtil.findFileInRead(project, pni.filePath) match {
|
||||
case (Some(virtualFile), Right(psiFile)) => HaskellReference.findIdentifierByLocation(project, virtualFile, psiFile, pni.lineNr, pni.columnNr, name).flatMap(HaskellPsiUtil.findDeclarationElement).toSeq
|
||||
@ -81,11 +81,11 @@ class HoogleByNameContributor extends ChooseByNameContributor {
|
||||
if (navigationItemByNameInfo.nonEmpty) {
|
||||
navigationItemByNameInfo
|
||||
} else {
|
||||
val identifiers = HaskellReference.findIdentifiersByModuleAndName(project, Seq(moduleName), name).toOption
|
||||
val identifiers = HaskellReference.findIdentifiersByModuleAndName(project, moduleName, name).toOption.map(_._2).toSeq
|
||||
if (identifiers.isEmpty) {
|
||||
NotFoundResult(moduleName, declaration)
|
||||
} else {
|
||||
identifiers.getOrElse(Seq()).map(e => HaskellPsiUtil.findDeclarationElement(e).getOrElse(e))
|
||||
identifiers.flatMap(e => HaskellPsiUtil.findDeclarationElement(e))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user