Skip to content

Commit

Permalink
refactor: 1) remove Service access from Object constructor 2) Snakema…
Browse files Browse the repository at this point in the history
…keFrameworkAPIProvider refactored (remove manual (name,ctx)->version maps creation) 3) support for additional fields for #536
  • Loading branch information
iromeo committed Oct 11, 2024
1 parent 66970c7 commit f0a37ae
Show file tree
Hide file tree
Showing 11 changed files with 409 additions and 212 deletions.
74 changes: 74 additions & 0 deletions snakemake_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ annotationsFormatVersion: 1
# Default Language Level used for all projects:
defaultVersion: "7.32.4"

# supported types of sections in each version:
# * 'introduced' - API was introduced
# * 'override' - API was changed, need to set all required fields, it is not incremental update to prev. version
# * 'deprecated' - Deprecate API and optionally provide Hint, how to fix it using `advice:`
# * 'removed' - API was finally removed

# 'type' specifies type of element (or its context). Supported values:
# * function - python functions (deprecations/removals only supported)
# * top-level - directives on file top-level, e.g. subworkflow, rule, use, wildcard_constraints, ..
Expand All @@ -14,108 +20,176 @@ defaultVersion: "7.32.4"

# =========================================
changelog:
# ---------------------------------------
- version: "8.0.0"

removed:
- name: "dynamic"
type: "function"
advice: "use checkpoints instead."

- name: "version"
type: "rule-like"
advice: "conda or container integration instead."

- name: "subworkflow"
type: "top-level"
advice: "use the module directive instead."

# ---------------------------------------
- version: "7.25.0"

introduced:
- name: "localrule"
type: "rule-like"

# ----------------------
- version: "7.7.0"

introduced:
- name: "retries"
type: "rule-like"

# ----------------------
- version: "7.0.0"

introduced:
- name: "template_engine"
type: "rule-like"

# ----------------------
- version: "6.15.0"

introduced:
- name: "default_target"
type: "rule-like"

# ----------------------
- version: "6.2.0"

introduced:
- name: "handover"
type: "rule-like"

# ----------------------
- version: "6.0.0"

introduced:
- name: "use"
type: "top-level"

- name: "module"
type: "top-level"

- name: "containerized"
type: "top-level"

- name: "containerized"
type: "rule-like"

deprecated:
- name: "subworkflow"
type: "top-level"
advice: "use the module directive instead."

# ----------------------
- version: "5.31.0"

introduced:
- name: "name"
type: "rule-like"

# ----------------------
- version: "5.12.0"

introduced:
- name: "cache"
type: "rule-like"

# ----------------------
- version: "5.11.0"

deprecated:
- name: "singularity"
type: "top-level"
advice: "use container directive instead."

- name: "singularity"
type: "rule-like"
advice: "use container directive instead."

introduced:
- name: "envvars"
type: "top-level"

- name: "container"
type: "top-level"

- name: "container"
type: "rule-like"

# ----------------------
- version: "5.9.0"

introduced:
- name: "envmodules"
type: "rule-like"

# ----------------------
- version: "5.4.0"

deprecated:
- name: "dynamic"
type: "function"
advice: "use checkpoints instead."

# ----------------------
- version: "4.8.0"

introduced:
- name: "cwl"
type: "rule-like"

- name: "conda"
type: "rule-like"
lambda_args:
- "wildcards"
- "params"
- "input"

- name: "singularity"
type: "rule-like"
keyword_args_allowed: False
multiple_args_allowed: False

- name: "singularity"
type: "top-level"

# ----------------------
- version: "3.8.0"
introduced:
- name: "wildcard_constraints"
type: "rule-like"

- name: "wildcard_constraints"
type: "top-level"

- name: "configfile"
type: "subworkflow"

# ----------------------
- version: "3.5.5"

introduced:
- name: "wrapper"
type: "rule-like"

# ----------------------
- version: "3.5.2"

introduced:
- name: "script"
type: "rule-like"

- name: "notebook"
type: "rule-like"
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import com.intellij.psi.util.PsiTreeUtil
import com.jetbrains.python.codeInsight.editorActions.moveUpDown.PyStatementMover
import com.jetbrains.python.psi.*
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.TOPLEVEL_ARGS_SECTION_KEYWORDS
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPIService
import com.jetbrains.snakecharm.lang.psi.*

open class SmkStatementMover : PyStatementMover() {
Expand Down Expand Up @@ -124,18 +124,23 @@ open class SmkStatementMover : PyStatementMover() {
}
}

private fun isNotAvailableForMoveInto(elementToMove: PsiElement, destination: PsiElement?): Boolean =
(elementToMove is SmkSection && elementToMove !is SmkRunSection &&
private fun isNotAvailableForMoveInto(elementToMove: PsiElement, destination: PsiElement?): Boolean {
val service = SnakemakeAPIService.getInstance()

return (elementToMove is SmkSection && elementToMove !is SmkRunSection &&
((destination is SmkRuleOrCheckpoint &&
elementToMove.sectionKeyword !in RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS) ||
elementToMove.sectionKeyword !in service.RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS) ||
(destination is SmkSubworkflow &&
elementToMove.sectionKeyword !in SnakemakeAPI.SUBWORKFLOW_SECTIONS_KEYWORDS) ||
(destination is SmkModule &&
elementToMove.sectionKeyword !in SnakemakeAPI.MODULE_SECTIONS_KEYWORDS) ||
elementToMove.sectionKeyword !in service.MODULE_SECTIONS_KEYWORDS) ||
(destination is SmkUse &&
elementToMove.sectionKeyword !in SnakemakeAPI.USE_SECTIONS_KEYWORDS)))
elementToMove.sectionKeyword !in service.USE_SECTIONS_KEYWORDS)))
}

private fun isAvailableForMoveOut(elementToMove: PsiElement, down: Boolean): Boolean {
val useSectionsKeywords = SnakemakeAPIService.getInstance().USE_SECTIONS_KEYWORDS

val statementList = getStatementList(elementToMove) ?: return true
val statements: Array<out PyStatement> = statementList.statements

Expand All @@ -158,12 +163,14 @@ open class SmkStatementMover : PyStatementMover() {
elementToMove,
down,
statements,
SmkRuleOrCheckpoint::class.java
SmkRuleOrCheckpoint::class.java,
useSectionsKeywords
)) || (elementToMove is SmkModuleArgsSection && searchForRuleLikeElement(
elementToMove,
down,
statements,
SmkModule::class.java
SmkModule::class.java,
useSectionsKeywords
))
) {
return true
Expand Down Expand Up @@ -191,10 +198,10 @@ open class SmkStatementMover : PyStatementMover() {
elementToMove: PsiElement,
down: Boolean,
statements: Array<out PyStatement>,
clazz: Class<T>
clazz: Class<T>,
useSectionsKeywords: Set<String>
): Boolean {
val parent =
PsiTreeUtil.getParentOfType(elementToMove, clazz)
val parent = PsiTreeUtil.getParentOfType(elementToMove, clazz)
if (!down && statements.first() == elementToMove || down && statements.last() == elementToMove) {

var sibling = if (!down) parent?.prevSibling else parent?.nextSibling
Expand All @@ -209,7 +216,7 @@ open class SmkStatementMover : PyStatementMover() {
// Check if not execution section
if (!(parentSibling is SmkUse &&
elementToMove is SmkSection &&
elementToMove.sectionKeyword !in SnakemakeAPI.USE_SECTIONS_KEYWORDS)
elementToMove.sectionKeyword !in useSectionsKeywords)
) {
return true
}
Expand Down Expand Up @@ -271,6 +278,8 @@ open class SmkStatementMover : PyStatementMover() {
statements: Array<PyStatement>,
clazz: Class<T>
): ScopeRange? {
val useSectionsKeywords = SnakemakeAPIService.getInstance().USE_SECTIONS_KEYWORDS

val parent =
PsiTreeUtil.getParentOfType(elementToMove, clazz)
if (!down && statements.first() == elementToMove || down && statements.last() == elementToMove) {
Expand All @@ -284,7 +293,7 @@ open class SmkStatementMover : PyStatementMover() {
// Check if not execution section
if (!(parentSibling is SmkUse &&
elementToMove is SmkSection &&
elementToMove.sectionKeyword !in SnakemakeAPI.USE_SECTIONS_KEYWORDS)
elementToMove.sectionKeyword !in useSectionsKeywords)
) {
val list = parentSibling.statementList
if (list.statements.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.jetbrains.snakecharm.codeInsight

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.ALLOWED_LAMBDA_OR_CALLABLE_ARGS
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPI.EXECUTION_SECTIONS_KEYWORDS
import com.jetbrains.snakecharm.codeInsight.SnakemakeAPICompanion.RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS_HARDCODED
import com.jetbrains.snakecharm.framework.SnakemakeFrameworkAPIProvider
import com.jetbrains.snakecharm.lang.SnakemakeNames
Expand Down Expand Up @@ -159,11 +163,6 @@ object SnakemakeAPI {
WORKFLOW_PEPFILE_KEYWORD
)

val RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS = RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS_HARDCODED +
SnakemakeFrameworkAPIProvider.getInstance().collectAllPossibleRuleOrCheckpointSubsectionKeywords()

val RULE_OR_CHECKPOINT_SECTION_KEYWORDS = (RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS + setOf(SECTION_RUN))

/**
* For codeInsight
*/
Expand All @@ -173,23 +172,9 @@ object SnakemakeAPI {
SnakemakeNames.SUBWORKFLOW_CONFIGFILE_KEYWORD
)

/**
* For modules codeInsight
*/
val MODULE_SECTIONS_KEYWORDS = setOf(
MODULE_SNAKEFILE_KEYWORD,
MODULE_CONFIG_KEYWORD,
MODULE_SKIP_VALIDATION_KEYWORD,
MODULE_META_WRAPPER_KEYWORD,
MODULE_REPLACE_PREFIX_KEYWORD
) + SnakemakeFrameworkAPIProvider.getInstance()
.collectAllPossibleModuleSubsectionKeywords()

/**
* For uses codeInsight
*/
val USE_SECTIONS_KEYWORDS = RULE_OR_CHECKPOINT_SECTION_KEYWORDS + SnakemakeFrameworkAPIProvider.getInstance()
.collectAllPossibleUseSubsectionKeywords() - EXECUTION_SECTIONS_KEYWORDS - SECTION_RUN

val USE_DECLARATION_KEYWORDS = setOf(
RULE_KEYWORD,
Expand Down Expand Up @@ -294,10 +279,6 @@ object SnakemakeAPI {
SECTION_INPUT,
),
)
val SECTION_LAMBDA_ARG_POSSIBLE_PARAMS: Set<String> =
ALLOWED_LAMBDA_OR_CALLABLE_ARGS.values.flatMap { it.asIterable() }.toMutableSet().also {
it.addAll(RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS)
}

/**
* Rule/checkpoint sections that does not allow keyword arguments
Expand Down Expand Up @@ -367,4 +348,37 @@ object SnakemakeAPICompanion {
SECTION_BENCHMARK, SECTION_MESSAGE, SECTION_SHELL, SECTION_THREADS,
SECTION_PRIORITY, SECTION_GROUP, SECTION_SHADOW,
)
}

@Service
class SnakemakeAPIService {
val RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS = RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS_HARDCODED +
SnakemakeFrameworkAPIProvider.getInstance().collectAllPossibleRuleOrCheckpointSubsectionKeywords()

val SECTION_LAMBDA_ARG_POSSIBLE_PARAMS: Set<String> =
ALLOWED_LAMBDA_OR_CALLABLE_ARGS.values.flatMap { it.asIterable() }.toMutableSet().also {
// TODO merge with deprecation provider keywords
it.addAll(RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS)
}

val RULE_OR_CHECKPOINT_SECTION_KEYWORDS = (RULE_OR_CHECKPOINT_ARGS_SECTION_KEYWORDS + setOf(SECTION_RUN))

val USE_SECTIONS_KEYWORDS = RULE_OR_CHECKPOINT_SECTION_KEYWORDS + SnakemakeFrameworkAPIProvider.getInstance()
.collectAllPossibleUseSubsectionKeywords() - EXECUTION_SECTIONS_KEYWORDS - SECTION_RUN

/**
* For modules codeInsight
*/
val MODULE_SECTIONS_KEYWORDS = setOf(
MODULE_SNAKEFILE_KEYWORD,
MODULE_CONFIG_KEYWORD,
MODULE_SKIP_VALIDATION_KEYWORD,
MODULE_META_WRAPPER_KEYWORD,
MODULE_REPLACE_PREFIX_KEYWORD
) + SnakemakeFrameworkAPIProvider.getInstance()
.collectAllPossibleModuleSubsectionKeywords()

companion object {
fun getInstance() = ApplicationManager.getApplication().getService(SnakemakeAPIService::class.java)!!
}
}
Loading

0 comments on commit f0a37ae

Please sign in to comment.