@@ -4,6 +4,15 @@ import mu.KotlinLogging
44import com.intellij.lang.Language
55import com.intellij.openapi.actionSystem.AnActionEvent
66import com.intellij.openapi.actionSystem.CommonDataKeys
7+ import com.intellij.openapi.actionSystem.PlatformDataKeys
8+ import com.intellij.openapi.project.Project
9+ import com.intellij.openapi.vfs.VirtualFile
10+ import com.intellij.psi.PsiDirectory
11+ import com.intellij.psi.PsiElement
12+ import com.intellij.psi.PsiFile
13+ import com.intellij.psi.PsiFileSystemItem
14+ import org.jetbrains.kotlin.idea.core.util.toPsiDirectory
15+ import org.jetbrains.kotlin.idea.core.util.toPsiFile
716
817private val logger = KotlinLogging .logger {}
918
@@ -16,15 +25,71 @@ abstract class LanguageAssistant {
1625 private val languages = mutableMapOf<String , LanguageAssistant >()
1726
1827 fun get (e : AnActionEvent ): LanguageAssistant ? {
19- e.getData(CommonDataKeys .PSI_FILE )?.language?.let { language ->
20- if (! languages.containsKey(language.id)) {
21- loadWithException(language)?.let {
22- languages.put(language.id, it.kotlin.objectInstance as LanguageAssistant )
28+ val project = e.project ? : return null
29+ val editor = e.getData(CommonDataKeys .EDITOR )
30+ if (editor != null ) {
31+ // The action is being called from editor
32+ e.getData(CommonDataKeys .PSI_FILE )?.language?.let { language ->
33+ updateLanguages(language)
34+ return languages[language.id]
35+ } ? : return null
36+ } else {
37+ // The action is being called from 'Project' tool window
38+ val language = when (val element = e.getData(CommonDataKeys .PSI_ELEMENT )) {
39+ is PsiFileSystemItem -> {
40+ e.getData(CommonDataKeys .VIRTUAL_FILE_ARRAY )?.let {
41+ findLanguageRecursively(project, it)
42+ }
2343 }
24- }
44+ is PsiElement -> {
45+ element.containingFile?.let { getLanguageFromFile(it) }
46+ }
47+ else -> {
48+ val someSelection = e.getData(PlatformDataKeys .SELECTED_ITEMS )? : return null
49+ someSelection.firstNotNullOfOrNull {
50+ when (it) {
51+ is PsiFileSystemItem -> findLanguageRecursively(project, arrayOf(it.virtualFile))
52+ is PsiElement -> it.language
53+ else -> { null }
54+ }
55+ }
56+ }
57+ } ? : return null
58+
59+ updateLanguages(language)
2560 return languages[language.id]
2661 }
27- return null
62+ }
63+
64+ private fun updateLanguages (language : Language ) {
65+ if (! languages.containsKey(language.id)) {
66+ loadWithException(language)?.let {
67+ languages.put(language.id, it.kotlin.objectInstance as LanguageAssistant )
68+ }
69+ }
70+ }
71+
72+ private fun getLanguageFromFile (file : PsiFile ): Language ? {
73+ updateLanguages(file.language)
74+ return if (languages.containsKey(file.language.id))
75+ file.language
76+ else
77+ null
78+ }
79+
80+ private fun findLanguageRecursively (directory : PsiDirectory ): Language ? {
81+ return directory.files
82+ .firstNotNullOfOrNull { getLanguageFromFile(it) } ? :
83+ directory.subdirectories.firstNotNullOfOrNull { findLanguageRecursively(it) }
84+ }
85+
86+ private fun findLanguageRecursively (project : Project , virtualFiles : Array <VirtualFile >): Language ? {
87+ val psiFiles = virtualFiles.mapNotNull { it.toPsiFile(project) }
88+ val psiDirectories = virtualFiles.mapNotNull { it.toPsiDirectory(project) }
89+
90+
91+ val fileLanguage = psiFiles.firstNotNullOfOrNull { getLanguageFromFile(it) }
92+ return fileLanguage ? : psiDirectories.firstNotNullOfOrNull { findLanguageRecursively(it) }
2893 }
2994 }
3095}
0 commit comments