Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import com.intellij.java.language.psi.*;
import com.intellij.java.language.psi.util.PsiUtil;
import com.intellij.java.analysis.impl.codeInspection.ControlFlowUtils;
import consulo.annotation.access.RequiredReadAction;
import consulo.java.analysis.localize.JavaAnalysisLocalize;
import consulo.language.psi.PsiElement;
import consulo.localize.LocalizeValue;
import consulo.util.collection.ContainerUtil;
import jakarta.annotation.Nonnull;

Expand Down Expand Up @@ -87,20 +89,20 @@ public DfaInstructionState[] visitControlTransfer(
@Nonnull DataFlowRunner runner,
@Nonnull DfaMemoryState state
) {
if (instruction instanceof ReturnInstruction && ((ReturnInstruction)instruction).isViaException()) {
ContainerUtil.addIfNotNull(myFailures, ((ReturnInstruction)instruction).getAnchor());
if (instruction instanceof ReturnInstruction returnInsn && returnInsn.isViaException()) {
ContainerUtil.addIfNotNull(myFailures, returnInsn.getAnchor());
}
else {
myMayReturnNormally = true;
}
return super.visitControlTransfer(instruction, runner, state);
}

private Map<PsiElement, String> getErrors() {
HashMap<PsiElement, String> errors = new HashMap<>();
private Map<PsiElement, LocalizeValue> getErrors() {
Map<PsiElement, LocalizeValue> errors = new HashMap<>();
for (PsiElement element : myViolations) {
if (!myNonViolations.contains(element)) {
errors.put(element, JavaAnalysisLocalize.inspectionContractCheckerContractViolated(myContract).get());
errors.put(element, JavaAnalysisLocalize.inspectionContractCheckerContractViolated(myContract));
}
}

Expand All @@ -111,13 +113,13 @@ private Map<PsiElement, String> getErrors() {
if (myContract.isTrivial()) {
errors.put(
element,
JavaAnalysisLocalize.inspectionContractCheckerMethodAlwaysFailsTrivial(myContract).get()
JavaAnalysisLocalize.inspectionContractCheckerMethodAlwaysFailsTrivial(myContract)
);
}
else {
errors.put(
element,
JavaAnalysisLocalize.inspectionContractCheckerMethodAlwaysFailsNontrivial(myContract).get()
JavaAnalysisLocalize.inspectionContractCheckerMethodAlwaysFailsNontrivial(myContract)
);
}
}
Expand All @@ -127,7 +129,7 @@ else if (myFailures.isEmpty() && errors.isEmpty() && myMayReturnNormally) {
PsiIdentifier nameIdentifier = myMethod.getNameIdentifier();
errors.put(
nameIdentifier != null ? nameIdentifier : myMethod,
JavaAnalysisLocalize.inspectionContractCheckerNoExceptionThrown(myContract).get()
JavaAnalysisLocalize.inspectionContractCheckerNoExceptionThrown(myContract)
);
}

Expand All @@ -143,7 +145,8 @@ private static boolean weCannotInferAnythingAboutMethodReturnValue(MethodCallIns
}
}

public static Map<PsiElement, String> checkContractClause(PsiMethod method, StandardMethodContract contract, boolean ownContract) {
@RequiredReadAction
public static Map<PsiElement, LocalizeValue> checkContractClause(PsiMethod method, StandardMethodContract contract, boolean ownContract) {
PsiCodeBlock body = method.getBody();
if (body == null) {
return Collections.emptyMap();
Expand All @@ -152,8 +155,8 @@ public static Map<PsiElement, String> checkContractClause(PsiMethod method, Stan
DataFlowRunner runner = new DataFlowRunner(method.getProject(), null);

PsiParameter[] parameters = method.getParameterList().getParameters();
final DfaMemoryState initialState = runner.createMemoryState();
final DfaValueFactory factory = runner.getFactory();
DfaMemoryState initialState = runner.createMemoryState();
DfaValueFactory factory = runner.getFactory();
for (int i = 0; i < contract.getParameterCount(); i++) {
ValueConstraint constraint = contract.getParameterConstraint(i);
DfaValue comparisonValue = constraint.getComparisonValue(factory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.intellij.java.analysis.impl.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.java.language.psi.*;
import consulo.java.analysis.localize.JavaAnalysisLocalize;
import consulo.localize.LocalizeValue;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.jetbrains.annotations.Contract;
Expand Down Expand Up @@ -83,11 +84,14 @@ public String toString() {
* @return null if this contract return value makes sense for the supplied return type.
* Otherwise the human-readable error message is returned.
*/
public final String getMethodCompatibilityProblem(PsiMethod method) {
//noinspection HardCodedStringLiteral
return validators().map(fn -> fn.apply(method)).filter(Objects::nonNull).findFirst()
.map((JavaAnalysisLocalize.contractReturnValueValidationPrefix(this).get() + ' ')::concat)
.orElse(null);
@Nonnull
public final LocalizeValue getMethodCompatibilityProblem(PsiMethod method) {
return validators()
.map(fn -> fn.apply(method))
.filter(Objects::nonNull)
.findFirst()
.map(value -> JavaAnalysisLocalize.contractReturnValueValidationProblem(myName, value))
.orElse(LocalizeValue.empty());
}

/**
Expand Down Expand Up @@ -575,7 +579,7 @@ Stream<Validator> validators() {

@Override
public boolean equals(Object obj) {
return this == obj || (obj instanceof ParameterReturnValue && ((ParameterReturnValue)obj).myParamNumber == myParamNumber);
return this == obj || (obj instanceof ParameterReturnValue paramReturnValue && paramReturnValue.myParamNumber == myParamNumber);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.siyeh.ig.psiutils.MethodCallUtils;
import consulo.annotation.access.RequiredReadAction;
import consulo.java.analysis.localize.JavaAnalysisLocalize;
import consulo.localize.LocalizeValue;
import consulo.util.lang.ObjectUtil;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
Expand Down Expand Up @@ -118,8 +119,12 @@ public String toString() {
if (this == UNKNOWN) {
return "(unknown)";
}
return IntStreamEx.range(myParameters.length).mapToEntry(idx -> "param" + (idx + 1), idx -> myParameters[idx])
.prepend("this", myThis).filterValues(b -> b).keys().joining(",");
return IntStreamEx.range(myParameters.length)
.mapToEntry(idx -> "param" + (idx + 1), idx -> myParameters[idx])
.prepend("this", myThis)
.filterValues(b -> b)
.keys()
.joining(",");
}

/**
Expand Down Expand Up @@ -208,31 +213,30 @@ else if (!part.isEmpty()) {
* @param method a method to apply the signature
* @return error message or null if signature is valid
*/
@Nullable
public static String checkSignature(@Nonnull String signature, @Nonnull PsiMethod method) {
@Nonnull
public static LocalizeValue checkSignature(@Nonnull String signature, @Nonnull PsiMethod method) {
try {
MutationSignature ms = parse(signature);
if (ms.myThis && method.hasModifierProperty(PsiModifier.STATIC)) {
return JavaAnalysisLocalize.mutationSignatureProblemStaticMethodCannotMutateThis().get();
if (ms.myThis && method.isStatic()) {
return JavaAnalysisLocalize.mutationSignatureProblemStaticMethodCannotMutateThis();
}
PsiParameter[] parameters = method.getParameterList().getParameters();
if (ms.myParameters.length > parameters.length) {
return JavaAnalysisLocalize.mutationSignatureProblemReferenceToParameterInvalid(ms.myParameters.length).get();
return JavaAnalysisLocalize.mutationSignatureProblemReferenceToParameterInvalid(ms.myParameters.length);
}
for (int i = 0; i < ms.myParameters.length; i++) {
if (ms.myParameters[i]) {
PsiType type = parameters[i].getType();
if (ClassUtils.isImmutable(type)) {
return JavaAnalysisLocalize.mutationSignatureProblemParameterHasImmutableType(i + 1, type.getPresentableText())
.get();
return JavaAnalysisLocalize.mutationSignatureProblemParameterHasImmutableType(i + 1, type.getPresentableText());
}
}
}
}
catch (IllegalArgumentException ex) {
return ex.getMessage();
return LocalizeValue.ofNullable(ex.getMessage());
}
return null;
return LocalizeValue.empty();
}

@Nonnull
Expand All @@ -256,8 +260,7 @@ public static MutationSignature fromCall(@Nullable PsiCall call) {
}
return fromMethod(method);
}
if (call instanceof PsiNewExpression) {
PsiNewExpression newExpression = (PsiNewExpression)call;
if (call instanceof PsiNewExpression newExpression) {
if (newExpression.isArrayCreation()) {
return PURE;
}
Expand All @@ -275,12 +278,12 @@ public static MutationSignature fromCall(@Nullable PsiCall call) {
Set<PsiClass> visited = new HashSet<>();
while (true) {
for (PsiField field : clazz.getFields()) {
if (!field.hasModifierProperty(PsiModifier.STATIC) && field.hasInitializer()) {
if (!field.isStatic() && field.hasInitializer()) {
return UNKNOWN;
}
}
for (PsiClassInitializer initializer : clazz.getInitializers()) {
if (!initializer.hasModifierProperty(PsiModifier.STATIC)) {
if (!initializer.isStatic()) {
return UNKNOWN;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
import com.intellij.java.language.psi.PsiModifierList;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.localize.InspectionGadgetsLocalize;
import consulo.annotation.access.RequiredReadAction;
import consulo.annotation.access.RequiredWriteAction;
import consulo.application.AccessToken;
import consulo.application.WriteAction;
import consulo.application.util.function.Processor;
import consulo.application.util.query.Query;
import consulo.language.editor.inspection.ProblemDescriptor;
import consulo.language.editor.refactoring.ui.ConflictsDialog;
Expand All @@ -37,79 +38,79 @@
import jakarta.annotation.Nonnull;

/**
* @author Bas Leijdekkers
*/
* @author Bas Leijdekkers
*/
public class MakeClassFinalFix extends InspectionGadgetsFix {
private final String className;

private final String className;

public MakeClassFinalFix(PsiClass aClass) {
className = aClass.getName();
}

@Override
@Nonnull
public LocalizeValue getName() {
return InspectionGadgetsLocalize.makeClassFinalFixName(className);
}

@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
final PsiClass containingClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (containingClass == null) {
return;
@RequiredReadAction
public MakeClassFinalFix(PsiClass aClass) {
className = aClass.getName();
}
final PsiModifierList modifierList = containingClass.getModifierList();
if (modifierList == null) {
return;
}
if (!isOnTheFly()) {
if (ClassInheritorsSearch.search(containingClass).findFirst() != null) {
return;
}
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
return;

@Nonnull
@Override
public LocalizeValue getName() {
return InspectionGadgetsLocalize.makeClassFinalFixName(className);
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass);
search.forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
conflicts.putValue(
containingClass,
InspectionGadgetsLocalize.zeroWillNoLongerBeOverridableBy1(
RefactoringUIUtil.getDescription(containingClass, false),
RefactoringUIUtil.getDescription(aClass, false)
).get()
);
return true;
}
});
final boolean conflictsDialogOK;
if (!conflicts.isEmpty()) {
final ConflictsDialog conflictsDialog = new ConflictsDialog(element.getProject(), conflicts, new Runnable() {
@Override
public void run() {
final AccessToken token = WriteAction.start();
try {

@Override
@RequiredWriteAction
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
PsiElement element = descriptor.getPsiElement();
PsiClass containingClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (containingClass == null) {
return;
}
PsiModifierList modifierList = containingClass.getModifierList();
if (modifierList == null) {
return;
}
if (!isOnTheFly()) {
if (ClassInheritorsSearch.search(containingClass).findFirst() != null) {
return;
}
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
return;
}
MultiMap<PsiElement, LocalizeValue> conflicts = new MultiMap<>();
Query<PsiClass> search = ClassInheritorsSearch.search(containingClass);
search.forEach(aClass -> {
conflicts.putValue(
containingClass,
InspectionGadgetsLocalize.zeroWillNoLongerBeOverridableBy1(
RefactoringUIUtil.getDescription(containingClass, false),
RefactoringUIUtil.getDescription(aClass, false)
)
);
return true;
});
boolean conflictsDialogOK;
if (!conflicts.isEmpty()) {
ConflictsDialog conflictsDialog = new ConflictsDialog(
element.getProject(),
conflicts,
() -> {
AccessToken token = WriteAction.start();
try {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
finally {
token.finish();
}
}
);
conflictsDialog.show();
conflictsDialogOK = conflictsDialog.isOK();
}
else {
conflictsDialogOK = true;
}
if (conflictsDialogOK) {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
finally {
token.finish();
}
}
});
conflictsDialog.show();
conflictsDialogOK = conflictsDialog.isOK();
} else {
conflictsDialogOK = true;
}
if (conflictsDialogOK) {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
}
}
Loading
Loading