Skip to content

Commit

Permalink
Merge branch 'master' into features/#355-module-use-support
Browse files Browse the repository at this point in the history
  • Loading branch information
dakochik authored Jul 28, 2021
2 parents 02f57b7 + b3588f2 commit 07dd033
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 23 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ plugins {
// gradle-intellij-plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
// This plugin allows you to build plugins for IntelliJ platform using specific
// IntelliJ SDK and bundled plugins.
id("org.jetbrains.intellij") version "1.1.4"
id("org.jetbrains.intellij") version "1.1.3"
// gradle-changelog-plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
id("org.jetbrains.changelog") version "1.2.1"
// detekt linter - read more: https://detekt.github.io/detekt/gradle.html
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ import com.jetbrains.snakecharm.lang.SnakemakeNames.SNAKEMAKE_IO_METHOD_REPORT
import com.jetbrains.snakecharm.lang.SnakemakeNames.SNAKEMAKE_IO_METHOD_TEMP
import com.jetbrains.snakecharm.lang.SnakemakeNames.SNAKEMAKE_IO_METHOD_TOUCH
import com.jetbrains.snakecharm.lang.SnakemakeNames.SNAKEMAKE_IO_METHOD_UNPACK
import com.jetbrains.snakecharm.lang.SnakemakeNames.WORKFLOW_CONTAINERIZED_KEYWORD
import com.jetbrains.snakecharm.lang.SnakemakeNames.WORKFLOW_CONTAINER_KEYWORD
import com.jetbrains.snakecharm.lang.SnakemakeNames.WORKFLOW_SINGULARITY_KEYWORD

/**
* Also see [ImplicitPySymbolsProvider] class
Expand Down Expand Up @@ -92,6 +95,9 @@ object SnakemakeAPI {
SECTION_WRAPPER, SECTION_CWL, SECTION_NOTEBOOK
)

/**
* Rule or checkpoint sections that allows only single argument
*/
val SINGLE_ARGUMENT_SECTIONS_KEYWORDS = setOf(
SECTION_SHELL, SECTION_SCRIPT, SECTION_WRAPPER,
SECTION_CWL, SECTION_BENCHMARK, SECTION_VERSION,
Expand All @@ -101,6 +107,14 @@ object SnakemakeAPI {
SECTION_HANDOVER, SECTION_CONTAINERIZED
)

/**
* Workflow top-level sections that allows only single argument
*/
val SINGLE_ARGUMENT_WORKFLOWS_KEYWORDS = setOf(
WORKFLOW_CONTAINERIZED_KEYWORD, WORKFLOW_CONTAINER_KEYWORD,
WORKFLOW_SINGULARITY_KEYWORD
)

/**
* For rules parsing
*/
Expand All @@ -117,6 +131,7 @@ object SnakemakeAPI {
SECTION_NAME,
SECTION_HANDOVER
)

val RULE_OR_CHECKPOINT_SECTION_KEYWORDS = (RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS + setOf(SECTION_RUN))

/**
Expand Down Expand Up @@ -245,7 +260,7 @@ object SnakemakeAPI {
}

/**
* Set of rule\checkpoint sections that does not expect keyword arguments
* Rule/checkpoint sections that does not allow keyword arguments
*/
val SECTIONS_WHERE_KEYWORD_ARGS_PROHIBITED = setOf(
SECTION_BENCHMARK, SECTION_VERSION, SECTION_MESSAGE, SECTION_SHELL, SECTION_THREADS, SECTION_SINGULARITY,
Expand All @@ -254,6 +269,15 @@ object SnakemakeAPI {
SECTION_NAME, SECTION_HANDOVER
)


/**
* Workflow top-level sections that does not allow keyword args
*/
val WORKFLOWS_WHERE_KEYWORD_ARGS_PROHIBITED = setOf(
WORKFLOW_CONTAINERIZED_KEYWORD, WORKFLOW_CONTAINER_KEYWORD,
WORKFLOW_SINGULARITY_KEYWORD
)

val IO_FLAG_2_SUPPORTED_SECTION: HashMap<String, List<String>> = hashMapOf(
SNAKEMAKE_IO_METHOD_ANCIENT to listOf(SECTION_INPUT),
SNAKEMAKE_IO_METHOD_PROTECTED to listOf(SECTION_OUTPUT, SECTION_LOG, SECTION_BENCHMARK),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import com.intellij.codeInspection.ProblemsHolder
import com.jetbrains.python.psi.PyArgumentList
import com.jetbrains.snakecharm.SnakemakeBundle
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.SINGLE_ARGUMENT_SECTIONS_KEYWORDS
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.SINGLE_ARGUMENT_WORKFLOWS_KEYWORDS
import com.jetbrains.snakecharm.lang.psi.SmkArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkModuleArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkRuleOrCheckpointArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkSubworkflowArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkWorkflowArgsSection

class SmkSectionMultipleArgsInspection : SnakemakeInspection() {
override fun buildVisitor(
Expand All @@ -21,8 +24,17 @@ class SmkSectionMultipleArgsInspection : SnakemakeInspection() {
}

override fun visitSmkRuleOrCheckpointArgsSection(st: SmkRuleOrCheckpointArgsSection) {
if (st.name in SINGLE_ARGUMENT_SECTIONS_KEYWORDS) {
checkArgumentList(st.argumentList, st.name!!)
checkArgumentList(st, SINGLE_ARGUMENT_SECTIONS_KEYWORDS)
}

override fun visitSmkWorkflowArgsSection(st: SmkWorkflowArgsSection) {
checkArgumentList(st, SINGLE_ARGUMENT_WORKFLOWS_KEYWORDS)
}

private fun checkArgumentList(st: SmkArgsSection, sectionKeywords: Set<String>) {
val keyword = st.sectionKeyword
if (keyword != null && keyword in sectionKeywords) {
checkArgumentList(st.argumentList, keyword)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import com.jetbrains.python.psi.PyArgumentList
import com.jetbrains.python.psi.PyKeywordArgument
import com.jetbrains.snakecharm.SnakemakeBundle
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.SECTIONS_WHERE_KEYWORD_ARGS_PROHIBITED
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.WORKFLOWS_WHERE_KEYWORD_ARGS_PROHIBITED
import com.jetbrains.snakecharm.lang.psi.SmkArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkModuleArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkRuleOrCheckpointArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkSubworkflowArgsSection
import com.jetbrains.snakecharm.lang.psi.SmkWorkflowArgsSection

class SmkSectionUnexpectedKeywordArgsInspection : SnakemakeInspection() {
override fun buildVisitor(
Expand All @@ -23,7 +25,19 @@ class SmkSectionUnexpectedKeywordArgsInspection : SnakemakeInspection() {
}

override fun visitSmkRuleOrCheckpointArgsSection(st: SmkRuleOrCheckpointArgsSection) {
if (st.sectionKeyword in SECTIONS_WHERE_KEYWORD_ARGS_PROHIBITED) {
checkArgumentList(st, SECTIONS_WHERE_KEYWORD_ARGS_PROHIBITED)
}

override fun visitSmkWorkflowArgsSection(st: SmkWorkflowArgsSection) {
checkArgumentList(st, WORKFLOWS_WHERE_KEYWORD_ARGS_PROHIBITED)
}

private fun checkArgumentList(
st: SmkArgsSection,
sectionKeywords: Set<String>,
) {
val keyword = st.sectionKeyword
if (keyword != null && keyword in sectionKeywords) {
checkArgumentList(st.argumentList, st)
}
}
Expand Down
28 changes: 14 additions & 14 deletions src/main/kotlin/com/jetbrains/snakecharm/lang/SnakemakeNames.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ object SnakemakeNames {
const val RULE_KEYWORD = "rule"
const val CHECKPOINT_KEYWORD = "checkpoint"

const val WORKFLOW_ONSUCCESS_KEYWORD = "onsuccess"
const val WORKFLOW_ONERROR_KEYWORD = "onerror"
const val WORKFLOW_ONSTART_KEYWORD = "onstart"
const val WORKFLOW_LOCALRULES_KEYWORD = "localrules"
const val WORKFLOW_RULEORDER_KEYWORD = "ruleorder"
const val WORKFLOW_CONFIGFILE_KEYWORD = "configfile"
const val WORKFLOW_REPORT_KEYWORD = "report"
const val WORKFLOW_WILDCARD_CONSTRAINTS_KEYWORD = "wildcard_constraints"
const val WORKFLOW_SINGULARITY_KEYWORD = "singularity"
const val WORKFLOW_INCLUDE_KEYWORD = "include"
const val WORKFLOW_WORKDIR_KEYWORD = "workdir"

const val WORKFLOW_LOCALRULES_KEYWORD = "localrules"

const val WORKFLOW_RULEORDER_KEYWORD = "ruleorder"

const val WORKFLOW_ONSUCCESS_KEYWORD = "onsuccess"
const val WORKFLOW_ONERROR_KEYWORD = "onerror"
const val WORKFLOW_ONSTART_KEYWORD = "onstart"
const val WORKFLOW_ENVVARS_KEYWORD = "envvars"
const val WORKFLOW_CONTAINER_KEYWORD = "container"
const val WORKFLOW_CONTAINERIZED_KEYWORD = "containerized" // => 6.0.0

const val SUBWORKFLOW_KEYWORD = "subworkflow"
const val SUBWORKFLOW_WORKDIR_KEYWORD = WORKFLOW_WORKDIR_KEYWORD
const val SUBWORKFLOW_CONFIGFILE_KEYWORD = WORKFLOW_CONFIGFILE_KEYWORD
const val SUBWORKFLOW_WORKDIR_KEYWORD = WORKFLOW_WORKDIR_KEYWORD
const val SUBWORKFLOW_CONFIGFILE_KEYWORD = WORKFLOW_CONFIGFILE_KEYWORD
const val SUBWORKFLOW_SNAKEFILE_KEYWORD = "snakefile"

const val MODULE_KEYWORD = "module"
Expand All @@ -51,9 +51,9 @@ object SnakemakeNames {
const val SECTION_VERSION = "version"
const val SECTION_MESSAGE = "message"
const val SECTION_THREADS = "threads"
const val SECTION_SINGULARITY = "singularity"
const val SECTION_SINGULARITY = WORKFLOW_SINGULARITY_KEYWORD
const val SECTION_PRIORITY = "priority"
const val SECTION_WILDCARD_CONSTRAINTS = "wildcard_constraints"
const val SECTION_WILDCARD_CONSTRAINTS = WORKFLOW_WILDCARD_CONSTRAINTS_KEYWORD
const val SECTION_GROUP = "group"
const val SECTION_CONDA = "conda" // >= 4.8
const val SECTION_RESOURCES = "resources"
Expand All @@ -65,8 +65,8 @@ object SnakemakeNames {
const val SECTION_SHADOW = "shadow"
const val SECTION_RUN = "run"
const val SECTION_CACHE = "cache" // >= 5.12.0
const val SECTION_CONTAINER = "container"
const val SECTION_CONTAINERIZED = "containerized" // => 6.0.0
const val SECTION_CONTAINER = WORKFLOW_CONTAINER_KEYWORD
const val SECTION_CONTAINERIZED = WORKFLOW_CONTAINERIZED_KEYWORD
const val SECTION_NOTEBOOK = "notebook"
const val SECTION_ENVMODULES = "envmodules" // >= 5.9
const val SECTION_NAME = "name" // >= 5.31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,22 @@ import com.jetbrains.snakecharm.lang.psi.*

object SmkSyntaxErrorAnnotator : SmkAnnotator() {
override fun visitSmkRuleOrCheckpointArgsSection(st: SmkRuleOrCheckpointArgsSection) {
if (!SnakemakeLanguageDialect.isInsideSmkFile(st)) {
findAndHighlightIncorrectArguments(st)
}

override fun visitSmkWorkflowArgsSection(st: SmkWorkflowArgsSection) {
findAndHighlightIncorrectArguments(st)
}

private fun findAndHighlightIncorrectArguments(argsSection: SmkArgsSection) {
if (!SnakemakeLanguageDialect.isInsideSmkFile(argsSection)) {
return
}

val seenKeywords2Value = HashMap<String, String>()
var encounteredKeywordArgument = false

st.argumentList?.arguments?.forEach { arg ->
argsSection.argumentList?.arguments?.forEach { arg ->
when (arg) {
is PyKeywordArgument -> {
arg.keyword?.let { keyword ->
Expand All @@ -30,7 +38,7 @@ object SmkSyntaxErrorAnnotator : SmkAnnotator() {
holder.newAnnotation(
ERROR,
SnakemakeBundle.message("ANN.keyword.argument.already.provided", keywordValue)
).range(arg.keywordNode!!).create()
).range(arg.keywordNode ?: return@let).create()
}
}
encounteredKeywordArgument = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,26 @@ Feature: Inspection for multiple arguments in various sections
| notebook |
| container |
| containerized |
| handover |
| handover |

Scenario Outline: Multiple arguments in workflow section
Given a snakemake project
Given I open a file "foo.smk" with text
"""
<section_name>: "a", "b", "c"
"""
And SmkSectionMultipleArgsInspection inspection is enabled
Then I expect inspection error on <"b"> with message
"""
Only one argument is allowed for '<section_name>' section.
"""
And I expect inspection error on <"c"> with message
"""
Only one argument is allowed for '<section_name>' section.
"""
When I check highlighting errors
Examples:
| section_name |
| containerized |
| singularity |
| container |
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,21 @@ Feature: Inspection for unexpected keyword arguments in section
| checkpoint | log |
| checkpoint | resources |
| checkpoint | wildcard_constraints |

Scenario Outline: Unexpected keyword arguments in workflow
Given a snakemake project
Given I open a file "foo.smk" with text
"""
<section_name>: a="foo.bar"
"""
And SmkSectionUnexpectedKeywordArgsInspection inspection is enabled
Then I expect inspection error on <a="foo.bar"> with message
"""
Section '<section_name>' does not support keyword arguments
"""
When I check highlighting errors
Examples:
| section_name |
| containerized |
| singularity |
| container |
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ Feature: Annotate syntax errors
"""
When I check highlighting errors

Scenario: Annotate keyword argument duplication in workflow
Given a snakemake project
Given I open a file "foo.smk" with text
"""
wildcard_constraints:
foo = ".*",
foo = "other.*"
"""
Then I expect inspection error on <foo> in <foo = "other.*"> with message
"""
Keyword argument already provided: foo = \".*\".
"""
When I check highlighting errors

Scenario Outline: Annotate positional argument after keyword argument
Given a snakemake project
Given I open a file "foo.smk" with text
Expand Down

0 comments on commit 07dd033

Please sign in to comment.