MultiStatusSimplifyPlatformStatus.java
/*******************************************************************************
* Copyright (c) 2025, 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.jdt.internal.corext.fix.helper;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFixCore.CompilationUnitRewriteOperationWithSourceRange;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.text.edits.TextEditGroup;
import org.sandbox.jdt.internal.common.HelperVisitorFactory;
import org.sandbox.jdt.internal.common.ReferenceHolder;
import org.sandbox.jdt.internal.corext.fix.SimplifyPlatformStatusFixCore;
/**
* Replaces a compile-time integer value of {@code 0} with the named
* {@link IStatus#OK} constant in a {@link MultiStatus} constructor.
*
* <p>Application-specific, nonzero or unresolved status codes are deliberately
* left unchanged. The cleanup must never normalize an arbitrary domain code to
* {@code IStatus.OK}.</p>
*/
public class MultiStatusSimplifyPlatformStatus extends AbstractSimplifyPlatformStatus {
private static final String OK_SIMPLE_NAME= "OK"; //$NON-NLS-1$
public MultiStatusSimplifyPlatformStatus() {
super(IStatus.OK);
}
@Override
public String getPreview(boolean afterRefactoring) {
if (afterRefactoring) {
return "MultiStatus status = new MultiStatus(pluginId, IStatus.OK, \"message\", null);\n"; //$NON-NLS-1$
}
return "MultiStatus status = new MultiStatus(pluginId, 0, \"message\", null);\n"; //$NON-NLS-1$
}
@Override
public void find(SimplifyPlatformStatusFixCore fixcore, CompilationUnit compilationUnit,
Set<CompilationUnitRewriteOperationWithSourceRange> operations, Set<ASTNode> nodesProcessed)
throws CoreException {
try {
ReferenceHolder<ASTNode, Object> holder= ReferenceHolder.createForNodes();
HelperVisitorFactory.forClassInstanceCreation(MultiStatus.class)
.in(compilationUnit)
.excluding(nodesProcessed)
.processEach(holder, (visited, data) -> {
if (nodesProcessed.contains(visited) || visited.arguments().size() != 4) {
return false;
}
ITypeBinding typeBinding= visited.resolveTypeBinding();
if (typeBinding == null
|| !MultiStatus.class.getName().equals(typeBinding.getErasure().getQualifiedName())) {
return false;
}
List<Expression> arguments= visited.arguments();
Expression codeArgument= arguments.get(1);
if (!hasConstantIntValue(codeArgument, IStatus.OK)
|| isCanonicalIStatusOkReference(codeArgument)
|| !StatusRewriteSupport.canDiscard(codeArgument)) {
return false;
}
operations.add(fixcore.rewrite(visited, data));
nodesProcessed.add(visited);
return false;
});
} catch (Exception exception) {
throw new CoreException(Status.error("Problem while finding MultiStatus simplifications", exception)); //$NON-NLS-1$
}
}
private static boolean isCanonicalIStatusOkReference(Expression expression) {
IBinding binding= null;
if (expression instanceof QualifiedName qualifiedName) {
binding= qualifiedName.resolveBinding();
} else if (expression instanceof SimpleName simpleName) {
binding= simpleName.resolveBinding();
}
if (!(binding instanceof IVariableBinding variableBinding)
|| !variableBinding.isField()
|| !OK_SIMPLE_NAME.equals(variableBinding.getName())) {
return false;
}
ITypeBinding declaringClass= variableBinding.getDeclaringClass();
return declaringClass != null
&& IStatus.class.getName().equals(declaringClass.getErasure().getQualifiedName());
}
@Override
public void rewrite(SimplifyPlatformStatusFixCore cleanup, final ClassInstanceCreation visited,
final CompilationUnitRewrite cuRewrite, TextEditGroup group,
ReferenceHolder<ASTNode, Object> holder) {
ASTRewrite rewrite= cuRewrite.getASTRewrite();
AST ast= cuRewrite.getRoot().getAST();
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
ImportRewriteContext importContext= new ContextSensitiveImportRewriteContext(cuRewrite.getRoot(),
visited.getStartPosition(), importRewrite);
ClassInstanceCreation newMultiStatus= ast.newClassInstanceCreation();
Name multiStatusName= ast.newName(importRewrite.addImport(MultiStatus.class.getName(), importContext));
newMultiStatus.setType(ast.newSimpleType(multiStatusName));
Name iStatusName= ast.newName(importRewrite.addImport(IStatus.class.getName(), importContext));
List<Expression> arguments= visited.arguments();
List<Expression> newArguments= newMultiStatus.arguments();
newArguments.add(ASTNodes.createMoveTarget(rewrite,
ASTNodes.getUnparenthesedExpression(arguments.get(0))));
QualifiedName okConstant= ast.newQualifiedName(iStatusName, ast.newSimpleName(OK_SIMPLE_NAME));
newArguments.add(okConstant);
newArguments.add(ASTNodes.createMoveTarget(rewrite,
ASTNodes.getUnparenthesedExpression(arguments.get(2))));
newArguments.add(ASTNodes.createMoveTarget(rewrite,
ASTNodes.getUnparenthesedExpression(arguments.get(3))));
ASTNodes.replaceButKeepComment(rewrite, visited, newMultiStatus, group);
StatusRewriteSupport.finish(cuRewrite, visited,
List.of(arguments.get(0), arguments.get(2), arguments.get(3)), List.of(arguments.get(1)), group,
MultiStatus.class.getName(), IStatus.class.getName());
}
}