Skip to content

Commit 93b7ee9

Browse files
committed
add local inspection and ability to swap incorrect range
1 parent 41ee66f commit 93b7ee9

File tree

10 files changed

+156
-2
lines changed

10 files changed

+156
-2
lines changed

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

Lines changed: 7 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/CrontabTimeRangeImpl.java

Lines changed: 17 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.github.xepozz.crontab.ide.inspections
2+
3+
import com.intellij.codeInspection.LocalQuickFix
4+
5+
abstract class CrontabScheduleQuickFix : LocalQuickFix {
6+
override fun getFamilyName() = this.name
7+
8+
abstract override fun getName(): String
9+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.github.xepozz.crontab.ide.inspections
2+
3+
import com.github.xepozz.crontab.language.psi.CrontabElementFactory
4+
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
5+
import com.intellij.codeInspection.ProblemDescriptor
6+
import com.intellij.codeInspection.ProblemsHolder
7+
import com.intellij.openapi.project.Project
8+
9+
object CrontabInspectionUtil {
10+
fun registerSwapRange(holder: ProblemsHolder, element: CrontabTimeRange) {
11+
val interval = "${element.second}-${element.first}"
12+
13+
holder.registerProblem(
14+
element,
15+
"Invalid time range. First interval must be greater than last.",
16+
object : CrontabScheduleQuickFix() {
17+
override fun getName() = "Replace with \"$interval\""
18+
19+
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
20+
val psiElement = descriptor.psiElement as? CrontabTimeRange ?: return
21+
if (psiElement.isWritable) {
22+
psiElement.replace(
23+
CrontabElementFactory.createCrontabTimeRange(
24+
project,
25+
psiElement.second,
26+
psiElement.first,
27+
)
28+
)
29+
}
30+
}
31+
}
32+
)
33+
}
34+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.github.xepozz.crontab.ide.inspections
2+
3+
import com.github.xepozz.crontab.language.CrontabFile
4+
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
5+
import com.github.xepozz.crontab.language.psi.CrontabVisitor
6+
import com.intellij.codeInspection.LocalInspectionTool
7+
import com.intellij.codeInspection.ProblemsHolder
8+
import com.intellij.psi.PsiElementVisitor
9+
import com.intellij.psi.PsiFile
10+
11+
class CrontabScheduleTimeRangeInspection : LocalInspectionTool() {
12+
override fun getStaticDescription(): String = "Crontab schedule mistakes"
13+
14+
override fun isAvailableForFile(file: PsiFile): Boolean = file is CrontabFile
15+
16+
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
17+
return object : CrontabVisitor() {
18+
override fun visitTimeRange(element: CrontabTimeRange) {
19+
if (element.first > element.second) {
20+
CrontabInspectionUtil.registerSwapRange(holder, element)
21+
}
22+
super.visitTimeRange(element)
23+
}
24+
}
25+
}
26+
27+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
elementTypeHolderClass="com.github.xepozz.crontab.language.psi.CrontabTypes"
1212
elementTypeClass="com.github.xepozz.crontab.language.psi.CrontabElementType"
1313
tokenTypeClass="com.github.xepozz.crontab.language.psi.CrontabTokenType"
14+
15+
psiImplUtilClass="com.github.xepozz.crontab.language.psi.impl.CrontabImplUtil"
1416
}
1517

1618
crontabFile ::= item_*
@@ -35,6 +37,8 @@ TIME_PERIODIC ::= (STAR SLASH NUMBER)
3537
TIME_RANGE ::= NUMBER HYPHEN NUMBER
3638
{
3739
pin=2
40+
extends="com.github.xepozz.crontab.language.psi.impl.CrontabTimeRangeBaseImpl"
41+
methods=[getFirst getSecond getIntRange]
3842
}
3943
TIME_RANGE_STEP ::= NUMBER SLASH NUMBER
4044
{
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.github.xepozz.crontab.language.psi
2+
3+
import com.github.xepozz.crontab.language.CrontabFile
4+
import com.github.xepozz.crontab.language.CrontabFileType
5+
import com.intellij.openapi.project.Project
6+
import com.intellij.psi.util.PsiTreeUtil
7+
8+
object CrontabElementFactory {
9+
fun createCrontabTimeRange(project: Project, first: Int, last: Int): CrontabTimeRange {
10+
val file = createFile(project, "$first-$last")
11+
12+
return PsiTreeUtil.findChildOfType(file, CrontabTimeRange::class.java) as CrontabTimeRange
13+
}
14+
15+
fun createFile(project: Project, text: String): CrontabFile {
16+
val name = "dummy.crontab"
17+
return com.intellij.psi.PsiFileFactory.getInstance(project)
18+
.createFileFromText(name, CrontabFileType.INSTANCE, text) as CrontabFile
19+
}
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.github.xepozz.crontab.language.psi.impl
2+
3+
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
4+
5+
object CrontabImplUtil {
6+
@JvmStatic
7+
fun getFirst(element: CrontabTimeRange) = element.node.firstChildNode.text.toInt()
8+
9+
@JvmStatic
10+
fun getSecond(element: CrontabTimeRange): Int = element.node.lastChildNode.text.toInt()
11+
12+
@JvmStatic
13+
fun getIntRange(element: CrontabTimeRange): IntRange = IntRange(
14+
element.node.lastChildNode.text.toInt(),
15+
element.node.firstChildNode.text.toInt(),
16+
)
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.github.xepozz.crontab.language.psi.impl
2+
3+
import com.github.xepozz.crontab.language.psi.CrontabTimeRange
4+
import com.github.xepozz.crontab.language.psi.CrontabTypes
5+
import com.intellij.extapi.psi.ASTWrapperPsiElement
6+
import com.intellij.lang.ASTNode
7+
8+
abstract class CrontabTimeRangeBaseImpl : ASTWrapperPsiElement, CrontabTimeRange {
9+
constructor(node: ASTNode) : super(node)
10+
11+
override fun getText(): String {
12+
val keyNode = this.node.findChildByType(CrontabTypes.CONTENT)
13+
14+
return keyNode?.text ?: ""
15+
}
16+
17+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
<lang.commenter
3737
language="Crontab"
3838
implementationClass="com.github.xepozz.crontab.ide.CrontabCommenter"/>
39+
<localInspection
40+
language="Crontab" enabledByDefault="true" level="ERROR"
41+
groupName="Crontab schedule" displayName="Crontab schedule"
42+
implementationClass="com.github.xepozz.crontab.ide.inspections.CrontabScheduleTimeRangeInspection"/>
3943

4044
<intentionAction>
4145
<language>Crontab</language>

0 commit comments

Comments
 (0)