1+ /*
2+ * Copyright (c) 2018 Patrick Scheibe
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in all
12+ * copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+ * SOFTWARE.
21+ */
22+
23+ package de.halirutan.mathematica.codeinsight.navigation
24+
25+ import com.intellij.navigation.ChooseByNameContributor
26+ import com.intellij.navigation.NavigationItem
27+ import com.intellij.openapi.diagnostic.Logger
28+ import com.intellij.openapi.project.Project
29+ import com.intellij.openapi.vfs.VirtualFile
30+ import com.intellij.psi.PsiElement
31+ import com.intellij.psi.search.FilenameIndex
32+ import com.intellij.psi.search.GlobalSearchScope
33+ import com.intellij.util.indexing.FileBasedIndex
34+ import de.halirutan.mathematica.index.packageexport.MathematicaPackageExportIndex
35+ import de.halirutan.mathematica.index.packageexport.PackageExportSymbol
36+ import de.halirutan.mathematica.lang.psi.api.Symbol
37+ import de.halirutan.mathematica.lang.resolve.GlobalDefinitionCollector
38+
39+ /* *
40+ * Provides GotoSymbol for all file level definitions that have a usage message.
41+ * @author patrick (10.05.18).
42+ */
43+ class GotoSymbolContributor : ChooseByNameContributor {
44+
45+ private val packageIndex = MathematicaPackageExportIndex .INDEX_ID
46+ private val logger = Logger .getInstance(" #de.halirutan.mathematica.codeinsight.navigation.GotoSymbolContributor" )
47+
48+ override fun getItemsByName (name : String? , pattern : String? , project : Project ? , includeNonProjectItems : Boolean ): Array <NavigationItem > {
49+ val project1 = project ? : return emptyArray()
50+ val scope = GlobalSearchScope .projectScope(project1)
51+ val name1 = name ? : return emptyArray()
52+ val keys = getPackageExportKeys(project1, includeNonProjectItems)
53+ val result = keys.filter { k -> k.symbol == name1 }.fold(ArrayList <NavigationItem >(), { accumulator, key ->
54+ val filesByName = FilenameIndex .getFilesByName(project1, key.fileName, scope)
55+ filesByName.forEach {
56+ it?.let {
57+ val symbol = it.findElementAt(key.offset)?.parent
58+ if (symbol is Symbol && symbol.symbolName == key.symbol) {
59+ val c = GlobalDefinitionCollector (symbol.getContainingFile())
60+ if (c.assignments.containsKey(symbol.symbolName)) {
61+ c.assignments[symbol.symbolName]?.forEach { assignmentProperty ->
62+ if (assignmentProperty.myAssignmentSymbol is Symbol && assignmentProperty.myLhsOfAssignment is PsiElement ) {
63+ accumulator.add(SymbolNavigationItem (assignmentProperty.myAssignmentSymbol, assignmentProperty.myLhsOfAssignment.text))
64+ }
65+ }
66+ }
67+ }
68+ }
69+ }
70+ accumulator
71+ })
72+ return result.toTypedArray()
73+ }
74+
75+ override fun getNames (project : Project ? , includeNonProjectItems : Boolean ): Array <String > {
76+ val nameArray = MathematicaPackageExportIndex .getSymbolNames(project).toTypedArray()
77+ logger.debug(" found ${nameArray.size} Mathematica symbols" )
78+ return nameArray
79+ }
80+
81+ private fun getPackageExportKeys (project : Project , includeNonProjectItems : Boolean ): ArrayList <PackageExportSymbol > {
82+ val fileIndex = FileBasedIndex .getInstance() ? : return arrayListOf ()
83+ val scope = if (includeNonProjectItems) GlobalSearchScope .projectScope(project) else GlobalSearchScope .allScope(project)
84+ val result: ArrayList <PackageExportSymbol > = arrayListOf ()
85+ fileIndex.getAllKeys(packageIndex, project).forEach {
86+ it?.let {
87+ val fileForKey = arrayListOf<VirtualFile >()
88+ val inScope = ! fileIndex.processValues(
89+ packageIndex,
90+ it,
91+ null ,
92+ { file, _ -> fileForKey.add(file); false },
93+ scope
94+ )
95+
96+ if (fileForKey.isNotEmpty() && inScope) {
97+ result.add(it)
98+ }
99+ }
100+ }
101+ return result
102+ }
103+ }
0 commit comments