Skip to content

Commit

Permalink
refactored: SmkUnrecognizedSectionInspection was divided into two dif…
Browse files Browse the repository at this point in the history
…ferent inspections,

Resolves: #408
  • Loading branch information
Dmitry Kochik committed Aug 12, 2021
1 parent 288d8fa commit 1076920
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.jetbrains.snakecharm.inspections

import com.intellij.codeInspection.LocalInspectionToolSession
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.util.elementType
import com.intellij.psi.util.parentOfType
import com.jetbrains.snakecharm.SnakemakeBundle
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI
import com.jetbrains.snakecharm.lang.psi.*
import com.jetbrains.snakecharm.lang.psi.elementTypes.SmkElementTypes

class SmkUnexpectedSectionInspection : SnakemakeInspection() {
override fun buildVisitor(
holder: ProblemsHolder,
isOnTheFly: Boolean,
session: LocalInspectionToolSession
) = object : SnakemakeInspectionVisitor(holder, session) {
override fun visitSmkSubworkflowArgsSection(st: SmkSubworkflowArgsSection) {
isSectionRecognized(st, SnakemakeAPI.SUBWORKFLOW_SECTIONS_KEYWORDS)
}

override fun visitSmkRuleOrCheckpointArgsSection(st: SmkRuleOrCheckpointArgsSection) {
if (st.originalElement.elementType == SmkElementTypes.USE_ARGS_SECTION_STATEMENT) {
isSectionRecognized(st, SnakemakeAPI.USE_SECTIONS_KEYWORDS)
} else {
isSectionRecognized(st, SnakemakeAPI.RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS)
}
}

override fun visitSmkModuleArgsSection(st: SmkModuleArgsSection) {
isSectionRecognized(st, SnakemakeAPI.MODULE_SECTIONS_KEYWORDS)
}

private fun isSectionRecognized(
argsSection: SmkArgsSection,
setOfValidNames: Set<String>
) {
val sectionNamePsi = argsSection.nameIdentifier
val sectionKeyword = argsSection.sectionKeyword
// Not argsSection.getParentRuleOrCheckPoint() because it is widely used in the project
val sectionName = argsSection.parentOfType<SmkRuleLike<*>>()?.sectionKeyword ?: return
if (sectionNamePsi == null || sectionKeyword == null || sectionKeyword in setOfValidNames) {
return
}
val appropriateSection = SmkUnrecognizedSectionInspection.getSectionBySubsection(sectionKeyword) ?: return
registerProblem(
sectionNamePsi,
SnakemakeBundle.message(
"INSP.NAME.section.unexpected",
sectionKeyword,
sectionName,
appropriateSection
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.USE_SECTIONS_KEYWORDS
import com.jetbrains.snakecharm.lang.psi.*
import com.jetbrains.snakecharm.lang.psi.elementTypes.SmkElementTypes
import com.jetbrains.snakecharm.inspections.quickfix.AddIgnoredElementQuickFix
import com.jetbrains.snakecharm.lang.SnakemakeNames.CHECKPOINT_KEYWORD
import com.jetbrains.snakecharm.lang.SnakemakeNames.MODULE_KEYWORD
import com.jetbrains.snakecharm.lang.SnakemakeNames.RULE_KEYWORD
import com.jetbrains.snakecharm.lang.SnakemakeNames.SUBWORKFLOW_KEYWORD
Expand All @@ -31,23 +30,19 @@ class SmkUnrecognizedSectionInspection : SnakemakeInspection() {
session: LocalInspectionToolSession
) = object : SnakemakeInspectionVisitor(holder, session) {
override fun visitSmkSubworkflowArgsSection(st: SmkSubworkflowArgsSection) {
isSectionRecognized(st, SUBWORKFLOW_SECTIONS_KEYWORDS, SUBWORKFLOW_KEYWORD)
isSectionRecognized(st, SUBWORKFLOW_SECTIONS_KEYWORDS)
}

override fun visitSmkRuleOrCheckpointArgsSection(st: SmkRuleOrCheckpointArgsSection) {
if (st.originalElement.elementType == SmkElementTypes.USE_ARGS_SECTION_STATEMENT) {
isSectionRecognized(st, USE_SECTIONS_KEYWORDS, USE_KEYWORD)
isSectionRecognized(st, USE_SECTIONS_KEYWORDS)
} else {
isSectionRecognized(
st,
RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS,
"$RULE_KEYWORD' or '$CHECKPOINT_KEYWORD"
)
isSectionRecognized(st, RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS)
}
}

override fun visitSmkModuleArgsSection(st: SmkModuleArgsSection) {
isSectionRecognized(st, MODULE_SECTIONS_KEYWORDS, MODULE_KEYWORD)
isSectionRecognized(st, MODULE_SECTIONS_KEYWORDS)
}

/**
Expand All @@ -56,8 +51,7 @@ class SmkUnrecognizedSectionInspection : SnakemakeInspection() {
*/
private fun isSectionRecognized(
argsSection: SmkArgsSection,
setOfValidNames: Set<String>,
sectionName: String
setOfValidNames: Set<String>
) {
val sectionNamePsi = argsSection.nameIdentifier
val sectionKeyword = argsSection.sectionKeyword
Expand All @@ -66,22 +60,14 @@ class SmkUnrecognizedSectionInspection : SnakemakeInspection() {
&& sectionKeyword !in ignoredItems
) {
val appropriateSection = getSectionBySubsection(sectionKeyword)
val message = if (appropriateSection == null) {
SnakemakeBundle.message("INSP.NAME.section.unrecognized.message", sectionKeyword)
} else {
SnakemakeBundle.message(
"INSP.NAME.section.unexpected",
sectionKeyword,
sectionName,
appropriateSection
if (appropriateSection == null) {
registerProblem(
sectionNamePsi,
SnakemakeBundle.message("INSP.NAME.section.unrecognized.message", sectionKeyword),
ProblemHighlightType.WEAK_WARNING,
null, AddIgnoredElementQuickFix(sectionKeyword)
)
}
registerProblem(
sectionNamePsi,
message,
ProblemHighlightType.WEAK_WARNING,
null, AddIgnoredElementQuickFix(sectionKeyword)
)
}
}

Expand All @@ -95,12 +81,14 @@ class SmkUnrecognizedSectionInspection : SnakemakeInspection() {
override fun createOptionsPanel(): JComponent? =
ListEditForm(SnakemakeBundle.message("INSP.NAME.section.unrecognized.ignored"), ignoredItems).contentPanel

private fun getSectionBySubsection(name: String) = when (name) {
in RULE_OR_CHECKPOINT_SECTION_KEYWORDS -> RULE_KEYWORD
in SUBWORKFLOW_SECTIONS_KEYWORDS -> SUBWORKFLOW_KEYWORD
in MODULE_SECTIONS_KEYWORDS -> MODULE_KEYWORD
in USE_SECTIONS_KEYWORDS -> USE_KEYWORD
else -> null
companion object {
fun getSectionBySubsection(name: String) = when (name) {
in RULE_OR_CHECKPOINT_SECTION_KEYWORDS -> RULE_KEYWORD
in SUBWORKFLOW_SECTIONS_KEYWORDS -> SUBWORKFLOW_KEYWORD
in MODULE_SECTIONS_KEYWORDS -> MODULE_KEYWORD
in USE_SECTIONS_KEYWORDS -> USE_KEYWORD
else -> null
}
}
}

11 changes: 11 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@
implementationClass="com.jetbrains.snakecharm.inspections.SmkUnrecognizedSectionInspection"
/>

<localInspection
language="Snakemake" shortName="SmkUnexpectedSectionInspection"
enabledByDefault="true"
level="ERROR"
suppressId="SmkUnexpectedSection"
bundle="SnakemakeBundle"
groupKey="INSP.GROUP.snakemake"
key="INSP.NAME.section.unexpected"
implementationClass="com.jetbrains.snakecharm.inspections.SmkUnexpectedSectionInspection"
/>

<localInspection
language="Snakemake" shortName="SmkUnusedLogFileInspection"
enabledByDefault="true"
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/SnakemakeBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ INSP.INTN.name.argument=Name argument
# SmkUnrecognizedSectionInspection
INSP.NAME.section.unrecognized=Section not recognized by SnakeCharm plugin
INSP.NAME.section.unrecognized.message=Section ''{0}'' isn''t recognized by SnakeCharm plugin or there could be a typo in the section name.
INSP.NAME.section.unexpected=Section ''{0}'' can''t be used in ''{1}'' but can be in ''{2}''
INSP.NAME.section.unrecognized.ignored=Ignored Sections
INSP.NAME.section.unrecognized.ignored.add=Ignore an unrecognized section ''{0}''

# SmkUnexpectedSectionInspection
INSP.NAME.section.unexpected=Section ''{0}'' can''t be used in ''{1}'' but can be in ''{2}''

# SmkUnusedLogFileInspection
INSP.NAME.unused.log.section=Looks like a log file won't be created, because it is not referenced from 'shell' or 'run' sections
INSP.INTN.unused.log.fix.add.to.shell.section=Append "{0}" to shell section command
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<html>
<body>
This inspection highlights the subsections which can't be used in current section,
but can be used in other sections.
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
Feature: Inspection if subsection is unexpected for section but it i appropriate for another section

Scenario: When 'use' section contains execution subsections
Given a snakemake project
Given I open a file "foo.smk" with text
"""
use rule RULE as NEW_RULE with:
run: ""
shell: ""
notebook: ""
script: ""
cwl: ""
wrapper: ""
"""
And SmkUnexpectedSectionInspection inspection is enabled
Then I expect inspection error on <run> with message
"""
Section 'run' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection error on <shell> with message
"""
Section 'shell' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection error on <notebook> with message
"""
Section 'notebook' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection error on <script> with message
"""
Section 'script' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection error on <cwl> with message
"""
Section 'cwl' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection error on <wrapper> with message
"""
Section 'wrapper' can't be used in 'use' but can be in 'rule'
"""
When I check highlighting errors

Scenario: Wrong sections
Given a snakemake project
Given I open a file "foo.smk" with text
"""
rule NAME:
skip_validation: True
checkpoint NAME2:
meta_wrapper: "wrapper"
subworkflow NAME3:
log: "log.txt"
module m:
workdir: "dir"
"""
And SmkUnexpectedSectionInspection inspection is enabled
Then I expect inspection error on <skip_validation> with message
"""
Section 'skip_validation' can't be used in 'rule' but can be in 'module'
"""
Then I expect inspection error on <meta_wrapper> with message
"""
Section 'meta_wrapper' can't be used in 'checkpoint' but can be in 'module'
"""
Then I expect inspection error on <log> with message
"""
Section 'log' can't be used in 'subworkflow' but can be in 'rule'
"""
Then I expect inspection error on <workdir> with message
"""
Section 'workdir' can't be used in 'module' but can be in 'subworkflow'
"""
When I check highlighting errors
Original file line number Diff line number Diff line change
Expand Up @@ -58,76 +58,4 @@ Feature: Inspection if section isn't recognized by SnakeCharm
| rule_like |
| rule |
| subworkflow |
| checkpoint |

Scenario: When 'use' section contains execution subsections
Given a snakemake project
Given I open a file "foo.smk" with text
"""
use rule RULE as NEW_RULE with:
run: ""
shell: ""
notebook: ""
script: ""
cwl: ""
wrapper: ""
unknown_section: ""
"""
And SmkUnrecognizedSectionInspection inspection is enabled
Then I expect inspection weak warning on <run> with message
"""
Section 'run' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <shell> with message
"""
Section 'shell' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <notebook> with message
"""
Section 'notebook' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <script> with message
"""
Section 'script' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <cwl> with message
"""
Section 'cwl' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <wrapper> with message
"""
Section 'wrapper' can't be used in 'use' but can be in 'rule'
"""
Then I expect inspection weak warning on <unknown_section> with message
"""
Section 'unknown_section' isn't recognized by SnakeCharm plugin or there could be a typo in the section name.
"""
When I check highlighting weak warnings

Scenario: Wrong sections
Given a snakemake project
Given I open a file "foo.smk" with text
"""
rule NAME:
skip_validation: True
subworkflow NAME2:
log: "log.txt"
module m:
workdir: "dir"
"""
And SmkUnrecognizedSectionInspection inspection is enabled
Then I expect inspection weak warning on <skip_validation> with message
"""
Section 'skip_validation' can't be used in 'rule' or 'checkpoint' but can be in 'module'
"""
Then I expect inspection weak warning on <log> with message
"""
Section 'log' can't be used in 'subworkflow' but can be in 'rule'
"""
Then I expect inspection weak warning on <workdir> with message
"""
Section 'workdir' can't be used in 'module' but can be in 'subworkflow'
"""
When I check highlighting weak warnings
| checkpoint |

0 comments on commit 1076920

Please sign in to comment.