Skip to content

Commit 4b17e86

Browse files
committed
collapse list of ranges
1 parent 74f118c commit 4b17e86

File tree

11 files changed

+157
-46
lines changed

11 files changed

+157
-46
lines changed

src/main/gen/com/github/xepozz/crontab/language/parser/CrontabParser.java

Lines changed: 16 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/gen/com/github/xepozz/crontab/language/psi/CrontabTimeListItem.java

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/gen/com/github/xepozz/crontab/language/psi/CrontabTimePointer.java

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/gen/com/github/xepozz/crontab/language/psi/impl/CrontabTimeListItemImpl.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/gen/com/github/xepozz/crontab/language/psi/impl/CrontabTimePointerImpl.java

Lines changed: 0 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.github.xepozz.crontab.ide
2+
3+
import com.github.xepozz.crontab.language.psi.CrontabTimeList
4+
5+
object CrontabTimeRangeUtil {
6+
fun expandRanges(element: CrontabTimeList): Set<Int> {
7+
val input = element.timeListItemList
8+
.map {
9+
when {
10+
it.timeRange != null -> "${it.timeRange!!.text}"
11+
it.timeExact != null -> "${it.timeExact!!.text}"
12+
else -> "0"
13+
}
14+
}
15+
return expandRanges(input)
16+
}
17+
18+
fun collapseRanges(element: CrontabTimeList): List<String> {
19+
val input = element.timeListItemList
20+
.map {
21+
when {
22+
it.timeRange != null -> "${it.timeRange!!.text}"
23+
it.timeExact != null -> "${it.timeExact!!.text}"
24+
else -> "0"
25+
}
26+
}
27+
return collapseRanges(input)
28+
}
29+
30+
fun collapseRanges(input: List<String>): List<String> {
31+
val numbers = expandRanges(input)
32+
33+
// Sort the numbers and then collapse ranges
34+
val sortedNumbers = numbers.sorted()
35+
val result = mutableListOf<String>()
36+
var rangeStart = sortedNumbers[0]
37+
var rangeEnd = sortedNumbers[0]
38+
39+
for (i in 1 until sortedNumbers.size) {
40+
if (sortedNumbers[i] == rangeEnd + 1) {
41+
rangeEnd = sortedNumbers[i]
42+
} else {
43+
if (rangeStart == rangeEnd) {
44+
result.add("$rangeStart")
45+
} else {
46+
result.add("$rangeStart-$rangeEnd")
47+
}
48+
rangeStart = sortedNumbers[i]
49+
rangeEnd = sortedNumbers[i]
50+
}
51+
}
52+
53+
// Add the last range
54+
if (rangeStart == rangeEnd) {
55+
result.add("$rangeStart")
56+
} else {
57+
result.add("$rangeStart-$rangeEnd")
58+
}
59+
60+
return result
61+
}
62+
63+
fun expandRanges(input: List<String>): Set<Int> {
64+
val numbers = mutableSetOf<Int>()
65+
66+
// Parse the input and collect all individual numbers and ranges
67+
for (item in input) {
68+
if (item.contains("-")) {
69+
// Handle range
70+
val parts = item.split("-")
71+
val start = parts[0].toInt()
72+
val end = parts[1].toInt()
73+
numbers.addAll(start..end)
74+
} else {
75+
// Handle individual number
76+
numbers.add(item.toInt())
77+
}
78+
}
79+
return numbers
80+
}
81+
}

src/main/kotlin/com/github/xepozz/crontab/ide/inspections/CrontabInspectionUtil.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.github.xepozz.crontab.ide.inspections
22

3+
import com.github.xepozz.crontab.ide.CrontabTimeRangeUtil
34
import com.github.xepozz.crontab.language.psi.CrontabElementFactory
5+
import com.github.xepozz.crontab.language.psi.CrontabTimeList
46
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
57
import com.intellij.codeInspection.ProblemDescriptor
8+
import com.intellij.codeInspection.ProblemHighlightType
69
import com.intellij.codeInspection.ProblemsHolder
710
import com.intellij.openapi.project.Project
811

@@ -55,4 +58,27 @@ object CrontabInspectionUtil {
5558
}
5659
)
5760
}
61+
62+
fun registerCollapseRangeList(holder: ProblemsHolder, element: CrontabTimeList) {
63+
holder.registerProblem(
64+
element,
65+
"List of intervals can be collapsed.",
66+
ProblemHighlightType.WARNING,
67+
object : CrontabScheduleQuickFix() {
68+
override fun getName() = "Collapse list"
69+
70+
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
71+
val psiElement = descriptor.psiElement as? CrontabTimeList ?: return
72+
if (psiElement.isWritable) {
73+
psiElement.replace(
74+
CrontabElementFactory.createCrontabTimeList(
75+
project,
76+
CrontabTimeRangeUtil.collapseRanges(psiElement),
77+
)
78+
)
79+
}
80+
}
81+
}
82+
)
83+
}
5884
}

src/main/kotlin/com/github/xepozz/crontab/ide/inspections/CrontabScheduleTimeRangeInspection.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.github.xepozz.crontab.ide.inspections
22

3+
import com.github.xepozz.crontab.ide.CrontabTimeRangeUtil
34
import com.github.xepozz.crontab.language.CrontabFile
5+
import com.github.xepozz.crontab.language.psi.CrontabTimeList
46
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
57
import com.github.xepozz.crontab.language.psi.CrontabVisitor
68
import com.intellij.codeInspection.LocalInspectionTool
@@ -24,6 +26,19 @@ class CrontabScheduleTimeRangeInspection : LocalInspectionTool() {
2426
}
2527
super.visitTimeRange(element)
2628
}
29+
30+
override fun visitTimeList(element: CrontabTimeList) {
31+
val before = element.text
32+
val after = CrontabTimeRangeUtil.collapseRanges(element).joinToString(",")
33+
34+
println("before $before")
35+
println("after $after")
36+
37+
if (before != after) {
38+
CrontabInspectionUtil.registerCollapseRangeList(holder, element)
39+
}
40+
super.visitTimeList(element)
41+
}
2742
}
2843
}
2944

src/main/kotlin/com/github/xepozz/crontab/language/parser/Crontab.bnf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ SCHEDULE ::= TIME_POINTER TIME_POINTER TIME_POINTER TIME_POINTER TIME_POINTER
2929
pin=1
3030
}
3131

32-
TIME_POINTER ::= TIME_PERIODIC | TIME_RANGE | TIME_RANGE_STEP | TIME_LIST | TIME_ANY | TIME_EXACT
32+
TIME_POINTER ::= TIME_PERIODIC | TIME_RANGE_STEP | TIME_LIST | TIME_ANY
3333
TIME_PERIODIC ::= (STAR SLASH NUMBER)
3434
{
3535
pin=2
@@ -44,11 +44,11 @@ TIME_RANGE_STEP ::= NUMBER SLASH NUMBER
4444
{
4545
pin=2
4646
}
47-
TIME_LIST ::= NUMBER COMMA TIME_LIST_ITEM (COMMA TIME_LIST_ITEM)*
47+
TIME_LIST ::= TIME_LIST_ITEM (COMMA TIME_LIST_ITEM)*
4848
{
4949
pin=2
5050
}
51-
TIME_LIST_ITEM ::= TIME_RANGE | NUMBER
51+
TIME_LIST_ITEM ::= TIME_RANGE | TIME_EXACT
5252

5353
TIME_ANY ::= STAR
5454
TIME_EXACT ::= NUMBER

src/main/kotlin/com/github/xepozz/crontab/language/psi/CrontabElementFactory.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import com.intellij.openapi.project.Project
66
import com.intellij.psi.util.PsiTreeUtil
77

88
object CrontabElementFactory {
9+
fun createCrontabTimeList(project: Project, values: List<String>): CrontabTimeList {
10+
val file = createFile(project, values.joinToString(","))
11+
12+
return PsiTreeUtil.findChildOfType(file, CrontabTimeList::class.java) as CrontabTimeList
13+
}
14+
915
fun createCrontabTimeRange(project: Project, first: Int, last: Int): CrontabTimeRange {
1016
val file = createFile(project, "$first-$last")
1117

0 commit comments

Comments
 (0)