mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
[lombok] IDEA-321989 prevent StringIndexOutOfBoundsException for short method names
GitOrigin-RevId: 67abc464309949d02319255c07cb1fd67403d8f8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
942bc7b32a
commit
de042e2e44
@@ -4,6 +4,7 @@ package de.plushnikov.intellij.plugin.inspection;
|
|||||||
import com.intellij.codeInspection.*;
|
import com.intellij.codeInspection.*;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||||
import com.intellij.psi.javadoc.PsiDocComment;
|
import com.intellij.psi.javadoc.PsiDocComment;
|
||||||
@@ -17,7 +18,10 @@ import org.jetbrains.annotations.Nls;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.intellij.util.ObjectUtils.tryCast;
|
import static com.intellij.util.ObjectUtils.tryCast;
|
||||||
|
|
||||||
@@ -56,7 +60,8 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
if (!annotation.getAttributes().isEmpty()) {
|
if (!annotation.getAttributes().isEmpty()) {
|
||||||
isGetterAtClassLevel = false;
|
isGetterAtClassLevel = false;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
annotatedFields.add(field);
|
annotatedFields.add(field);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -73,9 +78,10 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Pair<PsiField, PsiMethod>> allCandidates = new ArrayList<>(staticCandidates);
|
List<Pair<PsiField, PsiMethod>> allCandidates = new ArrayList<>(staticCandidates);
|
||||||
if (isGetterAtClassLevel && (!instanceCandidates.isEmpty() || !annotatedFields.isEmpty()) ) {
|
if (isGetterAtClassLevel && (!instanceCandidates.isEmpty() || !annotatedFields.isEmpty())) {
|
||||||
warnOrFix(psiClass, instanceCandidates, annotatedFields);
|
warnOrFix(psiClass, instanceCandidates, annotatedFields);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
allCandidates.addAll(instanceCandidates);
|
allCandidates.addAll(instanceCandidates);
|
||||||
}
|
}
|
||||||
for (Pair<PsiField, PsiMethod> candidate : allCandidates) {
|
for (Pair<PsiField, PsiMethod> candidate : allCandidates) {
|
||||||
@@ -114,17 +120,18 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
|| !method.isWritable()) {
|
|| !method.isWritable()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
|
|
||||||
final String methodName = method.getName();
|
final String methodName = method.getName();
|
||||||
final boolean isBooleanType = PsiTypes.booleanType().equals(returnType);
|
final boolean isBooleanType = PsiTypes.booleanType().equals(returnType);
|
||||||
if ((isBooleanType ? !methodName.startsWith("is") : !methodName.startsWith("get"))
|
if (isBooleanType ? !methodName.startsWith("is") : !methodName.startsWith("get")) {
|
||||||
|| methodName.length() == 3
|
|
||||||
|| Character.isDigit(methodName.charAt(3))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final String fieldName = isBooleanType
|
|
||||||
? methodName.substring(2, 3).toLowerCase(Locale.ROOT) + methodName.substring(3)
|
final String fieldName = StringUtil.getPropertyName(methodName);
|
||||||
: methodName.substring(3, 4).toLowerCase(Locale.ROOT) + methodName.substring(4);
|
if (StringUtil.isEmpty(fieldName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (method.getBody() == null) {
|
if (method.getBody() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -149,20 +156,19 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
if (thisExpression == null) {
|
if (thisExpression == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (thisExpression.getQualifier() != null) {
|
}
|
||||||
|
else if (thisExpression.getQualifier() != null) {
|
||||||
if (!thisExpression.getQualifier().isReferenceTo(psiClass)) {
|
if (!thisExpression.getQualifier().isReferenceTo(psiClass)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final @Nullable String identifier = fieldRef.getReferenceName();
|
final @Nullable String identifier = fieldRef.getReferenceName();
|
||||||
if (identifier == null) {
|
if (!fieldName.equals(identifier) && !StringUtil.capitalize(fieldName).equals(identifier)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!identifier.equals(fieldName)
|
|
||||||
&& !identifier.equals(fieldName.substring(0, 1).toUpperCase(Locale.ROOT) + fieldName.substring(1))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
|
||||||
final PsiField field = psiClass.findFieldByName(identifier, false);
|
final PsiField field = psiClass.findFieldByName(identifier, false);
|
||||||
if (field == null
|
if (field == null
|
||||||
|| !field.isWritable()
|
|| !field.isWritable()
|
||||||
@@ -172,7 +178,8 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
}
|
}
|
||||||
if (isMethodStatic) {
|
if (isMethodStatic) {
|
||||||
staticCandidates.add(Pair.pair(field, method));
|
staticCandidates.add(Pair.pair(field, method));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
instanceCandidates.add(Pair.pair(field, method));
|
instanceCandidates.add(Pair.pair(field, method));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -192,7 +199,8 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
psiClassNameIdentifier != null ? psiClassNameIdentifier.getTextRangeInParent() : psiClass.getTextRange(),
|
psiClassNameIdentifier != null ? psiClassNameIdentifier.getTextRangeInParent() : psiClass.getTextRange(),
|
||||||
fix);
|
fix);
|
||||||
} else if (myApplyFix) {
|
}
|
||||||
|
else if (myApplyFix) {
|
||||||
LombokGetterMayBeUsedFix.effectivelyDoFix(psiClass, fieldsAndMethods, annotatedFields);
|
LombokGetterMayBeUsedFix.effectivelyDoFix(psiClass, fieldsAndMethods, annotatedFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,8 +210,9 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
final LocalQuickFix fix = new LombokGetterMayBeUsedFix(field.getName());
|
final LocalQuickFix fix = new LombokGetterMayBeUsedFix(field.getName());
|
||||||
myHolder.registerProblem(method,
|
myHolder.registerProblem(method,
|
||||||
LombokBundle.message("inspection.lombok.getter.may.be.used.display.field.message",
|
LombokBundle.message("inspection.lombok.getter.may.be.used.display.field.message",
|
||||||
field.getName()), fix);
|
field.getName()), fix);
|
||||||
} else if (myApplyFix) {
|
}
|
||||||
|
else if (myApplyFix) {
|
||||||
LombokGetterMayBeUsedFix.effectivelyDoFix(field, method);
|
LombokGetterMayBeUsedFix.effectivelyDoFix(field, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,7 +244,8 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
final PsiElement element = descriptor.getPsiElement();
|
final PsiElement element = descriptor.getPsiElement();
|
||||||
if (element instanceof PsiMethod) {
|
if (element instanceof PsiMethod) {
|
||||||
new LombokGetterMayBeUsedVisitor(null, true).visitMethodForFix((PsiMethod)element);
|
new LombokGetterMayBeUsedVisitor(null, true).visitMethodForFix((PsiMethod)element);
|
||||||
} else if (element instanceof PsiClass) {
|
}
|
||||||
|
else if (element instanceof PsiClass) {
|
||||||
new LombokGetterMayBeUsedVisitor(null, true).visitClass((PsiClass)element);
|
new LombokGetterMayBeUsedVisitor(null, true).visitClass((PsiClass)element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +257,7 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
}
|
}
|
||||||
Project project = field.getProject();
|
Project project = field.getProject();
|
||||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||||
final PsiAnnotation annotation = factory.createAnnotationFromText("@"+LombokClassNames.GETTER, field);
|
final PsiAnnotation annotation = factory.createAnnotationFromText("@" + LombokClassNames.GETTER, field);
|
||||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(annotation);
|
JavaCodeStyleManager.getInstance(project).shortenClassReferences(annotation);
|
||||||
modifierList.addAfter(annotation, null);
|
modifierList.addAfter(annotation, null);
|
||||||
removeMethodAndMoveJavaDoc(field, method);
|
removeMethodAndMoveJavaDoc(field, method);
|
||||||
@@ -262,7 +272,7 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
removeMethodAndMoveJavaDoc(field, method);
|
removeMethodAndMoveJavaDoc(field, method);
|
||||||
}
|
}
|
||||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||||
final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@"+LombokClassNames.GETTER, aClass);
|
final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@" + LombokClassNames.GETTER, aClass);
|
||||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(newAnnotation);
|
JavaCodeStyleManager.getInstance(project).shortenClassReferences(newAnnotation);
|
||||||
final PsiModifierList modifierList = aClass.getModifierList();
|
final PsiModifierList modifierList = aClass.getModifierList();
|
||||||
if (modifierList == null) {
|
if (modifierList == null) {
|
||||||
@@ -295,14 +305,16 @@ public class LombokGetterMayBeUsedInspection extends LombokJavaInspectionBase im
|
|||||||
if (fieldJavaDoc == null) {
|
if (fieldJavaDoc == null) {
|
||||||
if (javaDocGetterText.isEmpty()) {
|
if (javaDocGetterText.isEmpty()) {
|
||||||
fieldJavaDoc = factory.createDocCommentFromText("/**\n*/");
|
fieldJavaDoc = factory.createDocCommentFromText("/**\n*/");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
fieldJavaDoc = factory.createDocCommentFromText("/**\n* -- GETTER --\n* " + javaDocGetterText + "\n*/");
|
fieldJavaDoc = factory.createDocCommentFromText("/**\n* -- GETTER --\n* " + javaDocGetterText + "\n*/");
|
||||||
}
|
}
|
||||||
for (PsiDocTag returnTag : returnTags) {
|
for (PsiDocTag returnTag : returnTags) {
|
||||||
fieldJavaDoc.add(returnTag);
|
fieldJavaDoc.add(returnTag);
|
||||||
}
|
}
|
||||||
field.getParent().addBefore(fieldJavaDoc, field);
|
field.getParent().addBefore(fieldJavaDoc, field);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
@NotNull PsiElement @NotNull [] fieldJavaDocChildren = Arrays.stream(fieldJavaDoc.getChildren())
|
@NotNull PsiElement @NotNull [] fieldJavaDocChildren = Arrays.stream(fieldJavaDoc.getChildren())
|
||||||
.filter(e -> e instanceof PsiDocToken)
|
.filter(e -> e instanceof PsiDocToken)
|
||||||
.toArray(PsiElement[]::new);
|
.toArray(PsiElement[]::new);
|
||||||
|
|||||||
@@ -40,4 +40,8 @@ public class LombokGetterMayBeUsedInspectionTest extends LightDaemonAnalyzerTest
|
|||||||
public void testInstanceAndStaticFields() {
|
public void testInstanceAndStaticFields() {
|
||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testShortMethods() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
public class ShortMethods {
|
||||||
|
private int someInt;
|
||||||
|
private boolean someBoolean;
|
||||||
|
private boolean b;
|
||||||
|
private boolean x;
|
||||||
|
|
||||||
|
<warning descr="Field 'someInt' may have Lombok @Getter">public int getSomeInt() {
|
||||||
|
return someInt;
|
||||||
|
}</warning>
|
||||||
|
|
||||||
|
<warning descr="Field 'someBoolean' may have Lombok @Getter">public boolean isSomeBoolean() {
|
||||||
|
return someBoolean;
|
||||||
|
}</warning>
|
||||||
|
|
||||||
|
<warning descr="Field 'b' may have Lombok @Getter">public boolean isB() {
|
||||||
|
return b;
|
||||||
|
}</warning>
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return someInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int get() {
|
||||||
|
return someInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user