Skip to content

Commit 6380fa3

Browse files
author
Dmitry
committed
New index for inherited rules was created. Behaviour of creating gutter icons in case of overridden rules was changed. Corresponding tests were extended.
Resolves: #462, #463, #429
1 parent 9c62dda commit 6380fa3

File tree

11 files changed

+208
-31
lines changed

11 files changed

+208
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Released on ...
1010
- TODO (see [#NNN](https://github.com/JetBrains-Research/snakecharm/issues/NNN))
1111

1212
### Fixed
13+
- Complex cases in creation of gutter icons for rule inheritance (see [#462](https://github.com/JetBrains-Research/snakecharm/issues/462), [#463](https://github.com/JetBrains-Research/snakecharm/issues/463))
1314
- Resolve for rule names in `use rule` section (see [#455](https://github.com/JetBrains-Research/snakecharm/issues/455))
1415
- Multiple args inspection in `workdir` case (see [#140](https://github.com/JetBrains-Research/snakecharm/issues/140))
1516
- `localrules` and `ruleorder` now take into account `use rule` (see [#448](https://github.com/JetBrains-Research/snakecharm/issues/448))

src/main/kotlin/com/jetbrains/snakecharm/SnakemakeRuleInheritanceMarkerProvider.kt

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import com.intellij.psi.PsiElement
99
import com.intellij.psi.search.GlobalSearchScope
1010
import com.intellij.psi.stubs.StubIndex
1111
import com.jetbrains.snakecharm.lang.psi.*
12-
import com.jetbrains.snakecharm.lang.psi.stubs.SmkModuleNameIndex.Companion.KEY
12+
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseInheritedRulesIndex
13+
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseInheritedRulesIndex.Companion.INHERITED_RULES_DECLARATION_VIA_WILDCARD
1314

1415
class SnakemakeRuleInheritanceMarkerProvider : RelatedItemLineMarkerProvider() {
1516

@@ -51,32 +52,32 @@ class SnakemakeRuleInheritanceMarkerProvider : RelatedItemLineMarkerProvider() {
5152
element: SmkRuleOrCheckpoint,
5253
result: MutableCollection<in RelatedItemLineMarkerInfo<*>>
5354
) {
54-
val currentFile = element.containingFile
5555
val identifier = when (val identifier = element.nameIdentifier) {
5656
is SmkUseNameIdentifier -> identifier.getNameBeforeWildcard()
5757
else -> identifier
5858
} ?: return
59-
val modulesFromStub = StubIndex.getInstance().getAllKeys(KEY, element.project)
6059
val module = element.let { ModuleUtilCore.findModuleForPsiElement(it.originalElement) } ?: return
61-
val files = mutableSetOf<SmkFile>()
62-
for (smkModule in modulesFromStub) {
63-
files.addAll(StubIndex.getElements(
64-
KEY,
65-
smkModule,
66-
module.project,
67-
GlobalSearchScope.moduleWithDependentsScope(module),
68-
SmkModule::class.java
69-
).mapNotNull { it.containingFile as? SmkFile })
70-
}
71-
if (currentFile is SmkFile) {
72-
files.add(currentFile)
73-
}
60+
val descendantsDefinedExplicitly = StubIndex.getElements(
61+
SmkUseInheritedRulesIndex.KEY,
62+
identifier.text,
63+
module.project,
64+
GlobalSearchScope.moduleWithDependentsScope(module),
65+
SmkUse::class.java
66+
)
67+
val potentialDescendants = StubIndex.getElements(
68+
SmkUseInheritedRulesIndex.KEY,
69+
INHERITED_RULES_DECLARATION_VIA_WILDCARD,
70+
module.project,
71+
GlobalSearchScope.moduleWithDependentsScope(module),
72+
SmkUse::class.java
73+
)
7474
val overrides = mutableListOf<SmkRuleOrCheckpoint>()
75-
files.forEach { file ->
76-
file.collectUses().forEach { (_, psi) ->
77-
if (psi.getImportedRules()?.firstOrNull { it == element } != null) {
78-
overrides.add(psi)
79-
}
75+
(descendantsDefinedExplicitly + potentialDescendants).forEach { descendant ->
76+
// We don't save it in stub because it requires 'resolve'
77+
// We compare resolve results even for descendantsDefinedExplicitly
78+
// Because there may be rules with the same names
79+
if (descendant.getImportedRules()?.contains(element) == true) {
80+
overrides.add(descendant)
8081
}
8182
}
8283
if (overrides.isEmpty()) {

src/main/kotlin/com/jetbrains/snakecharm/lang/psi/impl/refs/SmkRuleOrCheckpointNameReference.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,18 @@ class SmkRuleOrCheckpointNameReference(
6161
return results
6262
}
6363
val allImportedFiles = smkFile.collectIncludedFiles()
64+
val potentialModule = moduleRef?.reference?.resolve() as? SmkModule
6465
return results.filter { resolveResult ->
6566
// If we resolve module references, there must be only SmkModules
6667
(resolveResult.element is SmkModule && itIsModuleMameReference) ||
6768
// We don't want to suggest local resolve result for the reference of rule, which was imported
6869
(moduleRef != null // Module name reference is defined and resolve result is from another file
69-
&& element.containingFile.originalFile != resolveResult.element?.containingFile?.originalFile)
70+
&& element.containingFile.originalFile != resolveResult.element?.containingFile?.originalFile
71+
// Also, because of using indexes, we need to check if the resolve result file
72+
// Connected to the file, which was declared in moduleRef, via 'include' or 'module'
73+
// Later, allImportedFiles will be stored in cache
74+
&& resolveResult.element?.containingFile?.originalFile in ((potentialModule?.getPsiFile() as? SmkFile)?.collectIncludedFiles()
75+
?: listOf()))
7076
// OR There are no 'from *name*' combination, so it hasn't been imported
7177
|| (moduleRef == null && resolveResult.element?.containingFile?.originalFile in allImportedFiles)
7278
}.toMutableList()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.jetbrains.snakecharm.lang.psi.impl.stubs
2+
3+
import com.intellij.psi.stubs.*
4+
import com.jetbrains.python.psi.PyElement
5+
import com.jetbrains.python.psi.PyStubElementType
6+
import com.jetbrains.snakecharm.lang.psi.SmkRuleLike
7+
import com.jetbrains.snakecharm.lang.psi.stubs.RuleDescendantStub
8+
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseInheritedRulesIndex
9+
10+
abstract class SmkRuleDescendantElementType<StubT : RuleDescendantStub<*>, PsiT : PyElement>(
11+
debugName: String,
12+
private val nameIndexKey: StubIndexKey<String, out SmkRuleLike<*>>?
13+
) :
14+
PyStubElementType<StubT, PsiT>(debugName) {
15+
abstract fun createStub(name: String?, inheritedRules: List<String?>, parentStub: StubElement<*>?): StubT
16+
17+
override fun serialize(stub: StubT, dataStream: StubOutputStream) {
18+
dataStream.writeName(stub.name)
19+
dataStream.writeInt(stub.getInheritedRulesNames().size)
20+
stub.getInheritedRulesNames().forEach { name ->
21+
dataStream.writeName(name)
22+
}
23+
}
24+
25+
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): StubT {
26+
val name = dataStream.readNameString()
27+
val size = dataStream.readInt()
28+
val inheritedRules = mutableListOf<String?>()
29+
for (x in 0 until size) {
30+
inheritedRules.add(dataStream.readNameString())
31+
}
32+
return createStub(name, inheritedRules, parentStub)
33+
}
34+
35+
override fun indexStub(stub: StubT, sink: IndexSink) {
36+
if (nameIndexKey != null) {
37+
stub.name?.let { name ->
38+
sink.occurrence(nameIndexKey, name)
39+
}
40+
}
41+
stub.getInheritedRulesNames().forEach { inheritedName ->
42+
if (inheritedName != null) {
43+
sink.occurrence(SmkUseInheritedRulesIndex.KEY, inheritedName)
44+
}
45+
}
46+
super.indexStub(stub, sink)
47+
}
48+
}

src/main/kotlin/com/jetbrains/snakecharm/lang/psi/impl/stubs/SmkRuleLikeStubImpl.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ abstract class SmkRuleLikeStubImpl<StubT : NamedStub<PsiT>, PsiT>(
1818
override fun getName() = myName
1919
}
2020

21+
abstract class SmkRuleDescendantStubImpl<StubT : RuleDescendantStub<PsiT>, PsiT>(
22+
private val myName: String?,
23+
private val inheritedRulesNames: List<String?>,
24+
parent: StubElement<*>?,
25+
type: IStubElementType<StubT, PsiT>
26+
) : StubBase<PsiT>(parent, type), RuleDescendantStub<PsiT> where PsiT : PsiNamedElement, PsiT : PyElement {
27+
override fun getName() = myName
28+
override fun getInheritedRulesNames() = inheritedRulesNames
29+
}
30+
2131
class SmkCheckpointStubImpl(
2232
name: String?,
2333
parent: StubElement<*>?
@@ -42,5 +52,7 @@ class SmkModuleStubImpl(
4252

4353
class SmkUseStubImpl(
4454
name: String?,
55+
inheritedRulesNames: List<String?>,
4556
parent: StubElement<*>?
46-
) : SmkRuleLikeStubImpl<SmkUseStub, SmkUse>(name, parent, USE_DECLARATION_STATEMENT), SmkUseStub
57+
) : SmkRuleDescendantStubImpl<SmkUseStub, SmkUse>(name, inheritedRulesNames, parent, USE_DECLARATION_STATEMENT),
58+
SmkUseStub

src/main/kotlin/com/jetbrains/snakecharm/lang/psi/impl/stubs/SmkUseElementType.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@ import com.intellij.psi.PsiElement
55
import com.intellij.psi.stubs.StubElement
66
import com.jetbrains.snakecharm.lang.psi.SmkUse
77
import com.jetbrains.snakecharm.lang.psi.impl.SmkUseImpl
8+
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseInheritedRulesIndex.Companion.INHERITED_RULES_DECLARATION_VIA_WILDCARD
89
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseNameIndex.Companion.KEY
910
import com.jetbrains.snakecharm.lang.psi.stubs.SmkUseStub
1011

1112
class SmkUseElementType
12-
: SmkRuleLikeElementType<SmkUseStub, SmkUse>("SMK_USE_DECLARATION_STATEMENT", KEY) {
13+
: SmkRuleDescendantElementType<SmkUseStub, SmkUse>("SMK_USE_DECLARATION_STATEMENT", KEY) {
1314

14-
override fun createStub(name: String?, parentStub: StubElement<*>?): SmkUseStub =
15-
SmkUseStubImpl(name, parentStub)
15+
lateinit var psi: SmkUse
16+
17+
override fun createStub(name: String?, inheritedRules: List<String?>, parentStub: StubElement<*>?) =
18+
SmkUseStubImpl(name, inheritedRules, parentStub)
1619

1720
override fun createStub(psi: SmkUse, parentStub: StubElement<out PsiElement>?): SmkUseStub =
18-
createStub(psi.name, parentStub)
21+
createStub(
22+
psi.name,
23+
psi.getDefinedReferencesOfImportedRuleNames()?.map { it.text } ?: listOf(
24+
INHERITED_RULES_DECLARATION_VIA_WILDCARD
25+
),
26+
parentStub).also { this.psi = psi }
1927

2028
override fun createPsi(stub: SmkUseStub): SmkUse = SmkUseImpl(stub)
2129

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.jetbrains.snakecharm.lang.psi.stubs
2+
3+
import com.intellij.psi.PsiNamedElement
4+
import com.intellij.psi.stubs.NamedStub
5+
6+
/**
7+
* Stub of rule like element which inherits at least one rule
8+
*/
9+
interface RuleDescendantStub<T : PsiNamedElement> : NamedStub<T> {
10+
fun getInheritedRulesNames(): List<String?>
11+
}

src/main/kotlin/com/jetbrains/snakecharm/lang/psi/stubs/SmkStubs.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ interface SmkRuleStub : NamedStub<SmkRule>
77
interface SmkCheckpointStub : NamedStub<SmkCheckPoint>
88
interface SmkSubworkflowStub : NamedStub<SmkSubworkflow>
99
interface SmkModuleStub : NamedStub<SmkModule>
10-
interface SmkUseStub : NamedStub<SmkUse>
10+
interface SmkUseStub : RuleDescendantStub<SmkUse>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.jetbrains.snakecharm.lang.psi.stubs
2+
3+
import com.intellij.psi.stubs.StringStubIndexExtension
4+
import com.intellij.psi.stubs.StubIndexKey
5+
import com.jetbrains.snakecharm.lang.psi.SmkUse
6+
7+
class SmkUseInheritedRulesIndex :
8+
StringStubIndexExtension<SmkUse>() {
9+
override fun getKey() = KEY
10+
11+
companion object {
12+
const val INHERITED_RULES_DECLARATION_VIA_WILDCARD = "*"
13+
14+
val KEY = StubIndexKey.createIndexKey<String, SmkUse>("Smk.use.inheritedRules")
15+
}
16+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
<lang.documentationProvider language="Snakemake" implementationClass="com.jetbrains.snakecharm.lang.documentation.SmkWrapperDocumentation"/>
9595
<lang.psiStructureViewFactory language="Snakemake" implementationClass="com.jetbrains.snakecharm.lang.structureView.SmkStructureViewFactory"/>
9696
<stubIndex implementation="com.jetbrains.snakecharm.lang.psi.stubs.SmkRuleNameIndex"/>
97+
<stubIndex implementation="com.jetbrains.snakecharm.lang.psi.stubs.SmkUseInheritedRulesIndex"/>
9798
<stubIndex implementation="com.jetbrains.snakecharm.lang.psi.stubs.SmkCheckpointNameIndex"/>
9899
<stubIndex implementation="com.jetbrains.snakecharm.lang.psi.stubs.SmkUseNameIndex"/>
99100
<stubIndex implementation="com.jetbrains.snakecharm.lang.psi.stubs.SmkModuleNameIndex"/>

0 commit comments

Comments
 (0)