Skip to content

Commit e6bb197

Browse files
committed
Support literal. Add varargs and literal validators. Release 3.8.0
1 parent 4f2b71d commit e6bb197

File tree

12 files changed

+360
-5
lines changed

12 files changed

+360
-5
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
}
99

1010
group = "dev.rollczi"
11-
version = "3.7.0"
11+
version = "3.8.0"
1212

1313
repositories {
1414
mavenCentral()

src/main/java/dev/rollczi/litecommands/intellijplugin/api/psijava/PsiJavaArgument.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class PsiJavaArgument implements Argument {
88

99
static final Function<String, String> ARG = rawValue -> "<" + rawValue + ">";
10-
static final Function<String, String> FLAG = rawValue -> rawValue;
10+
static final Function<String, String> STATIC_VALUE = rawValue -> rawValue;
1111
static final Function<String, String> OPTIONAL = rawValue -> "[" + rawValue + "]";
1212
static final Function<String, String> JOIN = rawValue -> "<" + rawValue + "...>";
1313
static final Function<String, String> ARRAY = rawValue -> "[" + rawValue + "...]";

src/main/java/dev/rollczi/litecommands/intellijplugin/api/psijava/PsiJavaExecutorNode.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import dev.rollczi.litecommands.annotations.execute.Execute;
77
import dev.rollczi.litecommands.annotations.flag.Flag;
88
import dev.rollczi.litecommands.annotations.join.Join;
9+
import dev.rollczi.litecommands.annotations.literal.Literal;
910
import dev.rollczi.litecommands.annotations.optional.OptionalArg;
1011
import dev.rollczi.litecommands.annotations.quoted.Quoted;
1112
import dev.rollczi.litecommands.intellijplugin.api.Argument;
@@ -81,7 +82,14 @@ public class PsiJavaExecutorNode extends PsiJavaAbstractNode implements Executor
8182
// Flag
8283
(node, parameter) -> AnnotationFactory.from(Flag.class, parameter).stream()
8384
.findFirst()
84-
.map(holder -> new PsiJavaArgument(node, parameter, holder.asAnnotation().value(), PsiJavaArgument.FLAG))
85+
.map(holder -> new PsiJavaArgument(node, parameter, holder.asAnnotation().value(), PsiJavaArgument.STATIC_VALUE)),
86+
87+
(node, parameter) -> AnnotationFactory.from(Literal.class, parameter).stream()
88+
.findFirst()
89+
.map(holder -> {
90+
String[] values = holder.asAnnotation().value();
91+
return new PsiJavaArgument(node, parameter, values.length == 0 ? "" : values[0], PsiJavaArgument.STATIC_VALUE);
92+
})
8593
);
8694

8795
private final PsiJavaCommandNode parent;

src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/LiteInspectionProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.ExecuteValidationInspection;
1212
import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.CommandValidationInspection;
1313
import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.ShortcutValidationInspection;
14+
import dev.rollczi.litecommands.intellijplugin.inspection.parameter.LiteralAnnotationInspection;
1415
import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterMixedAnnotationsInspection;
1516
import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterNullableOptionalPrimitiveInspection;
1617
import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterNullableOptionalWrappedInspection;
18+
import dev.rollczi.litecommands.intellijplugin.inspection.parameter.VarargsAnnotationInspection;
1719
import org.jetbrains.annotations.NotNull;
1820

1921
public class LiteInspectionProvider implements InspectionToolProvider {
@@ -23,6 +25,8 @@ public class LiteInspectionProvider implements InspectionToolProvider {
2325
return new Class[]{
2426
ExecutorNotAnnotatedParameterInspection.class,
2527
ParameterNullableOptionalPrimitiveInspection.class,
28+
VarargsAnnotationInspection.class,
29+
LiteralAnnotationInspection.class,
2630
ParameterNullableOptionalWrappedInspection.class,
2731
ParameterMixedAnnotationsInspection.class,
2832
LegacyRouteInspection.class,

src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/annotation/LiteNullabilityAnnotationPackage.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
package dev.rollczi.litecommands.intellijplugin.inspection.annotation;
22

33
import com.intellij.codeInsight.Nullability;
4+
import com.intellij.codeInsight.NullabilityAnnotationInfo;
45
import com.intellij.codeInsight.annoPackages.AnnotationPackageSupport;
6+
import com.intellij.psi.PsiAnnotation;
7+
import com.intellij.psi.PsiElement;
58
import dev.rollczi.litecommands.annotations.argument.Arg;
69
import dev.rollczi.litecommands.annotations.flag.Flag;
710
import dev.rollczi.litecommands.annotations.join.Join;
11+
import dev.rollczi.litecommands.annotations.literal.Literal;
812
import dev.rollczi.litecommands.annotations.optional.OptionalArg;
13+
import dev.rollczi.litecommands.annotations.varargs.Varargs;
14+
import dev.rollczi.litecommands.intellijplugin.annotation.AnnotationFactory;
15+
import dev.rollczi.litecommands.intellijplugin.annotation.AnnotationHolder;
916
import java.util.List;
17+
import java.util.Optional;
1018
import org.jetbrains.annotations.NotNull;
19+
import org.jetbrains.annotations.Nullable;
1120

1221
public class LiteNullabilityAnnotationPackage implements AnnotationPackageSupport {
1322

1423
@Override
1524
public @NotNull List<String> getNullabilityAnnotations(@NotNull Nullability nullability) {
1625
return switch (nullability) {
1726
case NOT_NULL -> List.of(
18-
Arg.class.getName(),
1927
Join.class.getName(),
28+
Varargs.class.getName(),
29+
Literal.class.getName(),
2030
Flag.class.getName()
2131
);
2232
case NULLABLE -> List.of(
@@ -26,4 +36,21 @@ public class LiteNullabilityAnnotationPackage implements AnnotationPackageSuppor
2636
};
2737
}
2838

39+
@Override
40+
public @Nullable NullabilityAnnotationInfo getNullabilityByContainerAnnotation(@NotNull PsiAnnotation anno, @NotNull PsiElement context, PsiAnnotation.TargetType @NotNull [] types, boolean superPackage) {
41+
Optional<AnnotationHolder<Arg>> optionalArg = AnnotationFactory.fromPsiAnnotation(Arg.class, anno);
42+
43+
if (optionalArg.isPresent()) {
44+
Arg arg = optionalArg.get().asAnnotation();
45+
46+
return new NullabilityAnnotationInfo(
47+
anno,
48+
arg.nullable() ? Nullability.NULLABLE : Nullability.NOT_NULL,
49+
false
50+
);
51+
}
52+
53+
return null;
54+
}
55+
2956
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dev.rollczi.litecommands.intellijplugin.inspection.parameter;
2+
3+
import com.intellij.codeInspection.LocalQuickFix;
4+
import com.intellij.codeInspection.ProblemHighlightType;
5+
import com.intellij.codeInspection.ProblemsHolder;
6+
import com.intellij.psi.JavaElementVisitor;
7+
import com.intellij.psi.PsiAnnotation;
8+
import com.intellij.psi.PsiElementVisitor;
9+
import com.intellij.psi.PsiMethod;
10+
import com.intellij.psi.PsiParameter;
11+
import com.intellij.psi.PsiParameterList;
12+
import dev.rollczi.litecommands.annotations.execute.Execute;
13+
import dev.rollczi.litecommands.annotations.literal.Literal;
14+
import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection;
15+
import dev.rollczi.litecommands.intellijplugin.quickfix.ChangeParameterTypeQuickFix;
16+
import java.util.Set;
17+
import org.jetbrains.annotations.NotNull;
18+
19+
public class LiteralAnnotationInspection extends LiteInspection {
20+
21+
private static final Set<String> SUPPORTED_TYPES = Set.of(
22+
String.class.getName(),
23+
Void.class.getName()
24+
);
25+
26+
private static final String DISPLAY_NAME = "@Literal support only String type";
27+
private static final String PROBLEM_DESCRIPTION = "%s type is not supported by @Literal! Use a String instead.";
28+
29+
public LiteralAnnotationInspection() {
30+
super(DISPLAY_NAME);
31+
}
32+
33+
@Override
34+
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
35+
return new MethodVisitor(holder);
36+
}
37+
38+
private static class MethodVisitor extends JavaElementVisitor {
39+
40+
private final ProblemsHolder holder;
41+
42+
public MethodVisitor(ProblemsHolder holder) {
43+
this.holder = holder;
44+
}
45+
46+
@Override
47+
public void visitMethod(@NotNull PsiMethod method) {
48+
PsiAnnotation annotation = method.getAnnotation(Execute.class.getName());
49+
50+
if (annotation == null) {
51+
return;
52+
}
53+
54+
PsiParameterList parameterList = method.getParameterList();
55+
56+
for (PsiParameter parameter : parameterList.getParameters()) {
57+
PsiAnnotation[] annotations = parameter.getAnnotations();
58+
59+
for (PsiAnnotation psiAnnotation : annotations) {
60+
if (Literal.class.getName().equals(psiAnnotation.getQualifiedName())) {
61+
this.checkLiteralAnnotation(parameter);
62+
}
63+
}
64+
}
65+
}
66+
67+
private void checkLiteralAnnotation(PsiParameter parameter) {
68+
if (SUPPORTED_TYPES.contains(parameter.getType().getCanonicalText())) {
69+
return;
70+
}
71+
72+
String problemMessage = String.format(PROBLEM_DESCRIPTION, parameter.getType().getCanonicalText());
73+
74+
holder.registerProblem(parameter, problemMessage, ProblemHighlightType.GENERIC_ERROR, fixes(parameter));
75+
}
76+
77+
private LocalQuickFix[] fixes(PsiParameter parameter) {
78+
return new LocalQuickFix[] { new ChangeParameterTypeQuickFix(type -> "Replace to String", parameter, old -> "String") };
79+
}
80+
}
81+
82+
}

src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/parameter/ParameterMixedAnnotationsInspection.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import dev.rollczi.litecommands.annotations.execute.Execute;
2020
import dev.rollczi.litecommands.annotations.flag.Flag;
2121
import dev.rollczi.litecommands.annotations.join.Join;
22+
import dev.rollczi.litecommands.annotations.literal.Literal;
2223
import dev.rollczi.litecommands.annotations.optional.OptionalArg;
24+
import dev.rollczi.litecommands.annotations.varargs.Varargs;
2325
import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection;
2426
import dev.rollczi.litecommands.intellijplugin.quickfix.ReplaceQuickFix;
2527
import java.util.ArrayList;
@@ -37,7 +39,9 @@ public class ParameterMixedAnnotationsInspection extends LiteInspection {
3739
Arg.class.getName(),
3840
OptionalArg.class.getName(),
3941
Flag.class.getName(),
40-
Join.class.getName()
42+
Join.class.getName(),
43+
Literal.class.getName(),
44+
Varargs.class.getName()
4145
);
4246

4347
private static final String DISPLAY_NAME = "Mixed annotations";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package dev.rollczi.litecommands.intellijplugin.inspection.parameter;
2+
3+
import com.intellij.codeInspection.LocalQuickFix;
4+
import com.intellij.codeInspection.ProblemHighlightType;
5+
import com.intellij.codeInspection.ProblemsHolder;
6+
import com.intellij.psi.JavaElementVisitor;
7+
import com.intellij.psi.PsiAnnotation;
8+
import com.intellij.psi.PsiElementVisitor;
9+
import com.intellij.psi.PsiMethod;
10+
import com.intellij.psi.PsiParameter;
11+
import com.intellij.psi.PsiParameterList;
12+
import dev.rollczi.litecommands.annotations.execute.Execute;
13+
import dev.rollczi.litecommands.annotations.varargs.Varargs;
14+
import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection;
15+
import dev.rollczi.litecommands.intellijplugin.quickfix.ChangeParameterTypeQuickFix;
16+
import dev.rollczi.litecommands.intellijplugin.quickfix.WrapParameterTypeQuickFix;
17+
import dev.rollczi.litecommands.intellijplugin.util.LiteTypeChecks;
18+
import java.util.List;
19+
import java.util.Set;
20+
import org.jetbrains.annotations.NotNull;
21+
22+
public class VarargsAnnotationInspection extends LiteInspection {
23+
24+
private static final String DISPLAY_NAME = "@Varargs support only collection types";
25+
private static final String PROBLEM_DESCRIPTION = "%s type is not supported by @Varargs! Use a collection instead.";
26+
27+
public VarargsAnnotationInspection() {
28+
super(DISPLAY_NAME);
29+
}
30+
31+
@Override
32+
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
33+
return new MethodVisitor(holder);
34+
}
35+
36+
private static class MethodVisitor extends JavaElementVisitor {
37+
38+
private final ProblemsHolder holder;
39+
40+
public MethodVisitor(ProblemsHolder holder) {
41+
this.holder = holder;
42+
}
43+
44+
@Override
45+
public void visitMethod(@NotNull PsiMethod method) {
46+
PsiAnnotation annotation = method.getAnnotation(Execute.class.getName());
47+
48+
if (annotation == null) {
49+
return;
50+
}
51+
52+
PsiParameterList parameterList = method.getParameterList();
53+
54+
for (PsiParameter parameter : parameterList.getParameters()) {
55+
PsiAnnotation[] annotations = parameter.getAnnotations();
56+
57+
for (PsiAnnotation psiAnnotation : annotations) {
58+
if (Varargs.class.getName().equals(psiAnnotation.getQualifiedName())) {
59+
this.checkVarargsAnnotation(parameter);
60+
}
61+
}
62+
}
63+
}
64+
65+
private void checkVarargsAnnotation(PsiParameter parameter) {
66+
if (LiteTypeChecks.isArrayWrapper(parameter.getType(), parameter.getProject())) {
67+
return;
68+
}
69+
70+
String problemMessage = String.format(PROBLEM_DESCRIPTION, parameter.getType().getCanonicalText());
71+
72+
holder.registerProblem(parameter, problemMessage, ProblemHighlightType.GENERIC_ERROR, fixes(parameter));
73+
}
74+
75+
private LocalQuickFix[] fixes(PsiParameter parameter) {
76+
return new LocalQuickFix[] {
77+
new WrapParameterTypeQuickFix(parameter, List.class),
78+
new WrapParameterTypeQuickFix(parameter, Set.class),
79+
new ChangeParameterTypeQuickFix(type -> "Replace to " + type, parameter, type -> type + "[]"),
80+
new ChangeParameterTypeQuickFix(type -> "Replace to " + type, parameter, type -> type + "...")
81+
};
82+
}
83+
84+
}
85+
86+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package dev.rollczi.litecommands.intellijplugin.quickfix;
2+
3+
import com.intellij.codeInspection.ProblemDescriptor;
4+
import com.intellij.openapi.editor.Document;
5+
import com.intellij.openapi.editor.RangeMarker;
6+
import com.intellij.openapi.project.Project;
7+
import com.intellij.psi.PsiFile;
8+
import com.intellij.psi.PsiParameter;
9+
import com.intellij.psi.PsiTypeElement;
10+
import dev.rollczi.litecommands.intellijplugin.util.PsiImportUtil;
11+
import java.util.function.Function;
12+
import org.jetbrains.annotations.NotNull;
13+
14+
public class ChangeParameterTypeQuickFix extends ReplaceQuickFix {
15+
16+
private final String[] imports;
17+
18+
public ChangeParameterTypeQuickFix(Function<String, String> info, PsiParameter parameter, Class<?> type) {
19+
this(info, parameter, oldType -> type.getSimpleName(), type.getName());
20+
}
21+
22+
public ChangeParameterTypeQuickFix(Function<String, String> info, PsiParameter parameter, Function<String, String> mapper, String... imports) {
23+
super(
24+
info.apply(mappedType(parameter, mapper)),
25+
createTypeRange(parameter),
26+
mappedType(parameter, mapper)
27+
);
28+
29+
this.imports = imports;
30+
}
31+
32+
private static String mappedType(PsiParameter parameter, Function<String, String> mapper) {
33+
return mapper.apply(parameter.getType().getPresentableText());
34+
}
35+
36+
private static RangeMarker createTypeRange(PsiParameter parameter) {
37+
PsiFile file = parameter.getContainingFile();
38+
Document document = file.getViewProvider().getDocument();
39+
PsiTypeElement typeElement = parameter.getTypeElement();
40+
41+
if (typeElement == null) {
42+
return document.createRangeMarker(0, 0);
43+
}
44+
45+
return document.createRangeMarker(typeElement.getTextRange());
46+
}
47+
48+
@Override
49+
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
50+
super.applyFix(project, descriptor);
51+
52+
for (String importType : imports) {
53+
PsiImportUtil.importClass(descriptor.getPsiElement(), importType);
54+
}
55+
}
56+
57+
}

0 commit comments

Comments
 (0)