UseFunctionalCallCleanUpCore.java
/*******************************************************************************
* Copyright (c) 2021 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.ui.fix;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_ENABLED;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_FROM_CLASSIC_FOR;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_FROM_ENHANCED_FOR;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_FROM_ITERATOR_WHILE;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_FROM_STREAM;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.LOOP_CONVERSION_TARGET_FORMAT;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.USEFUNCTIONALLOOP_CLEANUP;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.USEFUNCTIONALLOOP_CLEANUP_V2;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.USEFUNCTIONALLOOP_FORMAT_FOR;
import static org.sandbox.jdt.internal.corext.fix2.MYCleanUpConstants.USEFUNCTIONALLOOP_FORMAT_WHILE;
import static org.sandbox.jdt.internal.ui.fix.MultiFixMessages.FunctionalCallCleanUpFix_refactor;
import static org.sandbox.jdt.internal.ui.preferences.cleanup.CleanUpMessages.LoopConversion_Description;
import java.util.EnumSet;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.internal.ui.fix.AbstractCleanUp;
import org.eclipse.jdt.ui.cleanup.CleanUpContext;
import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
import org.sandbox.jdt.internal.corext.fix.UseFunctionalCallFixCore;
import org.sandbox.jdt.internal.corext.fix.helper.LoopConversionService;
import org.sandbox.jdt.internal.corext.fix.helper.LoopTargetFormat;
public class UseFunctionalCallCleanUpCore extends AbstractCleanUp {
private Map<String, String> optionsMap = Map.of();
public UseFunctionalCallCleanUpCore(Map<String, String> options) {
super(options);
optionsMap = options;
}
public UseFunctionalCallCleanUpCore() {
}
@Override
public void setOptions(CleanUpOptions options) {
super.setOptions(options);
optionsMap = options.getKeys().stream().collect(Collectors.toMap(key -> key, options::getValue));
}
@Override
public CleanUpRequirements getRequirements() {
return new CleanUpRequirements(requireAST(), false, false, null);
}
public boolean requireAST() {
return isEnabled(USEFUNCTIONALLOOP_CLEANUP) || isEnabled(USEFUNCTIONALLOOP_CLEANUP_V2) || isEnabled(LOOP_CONVERSION_ENABLED);
}
@Override
public ICleanUpFix createFix(CleanUpContext context) throws CoreException {
if (context.getAST() == null || !requireAST()) {
return null;
}
return LoopConversionService.analyze(context.getAST(), computeFixSet()).createFix(FunctionalCallCleanUpFix_refactor);
}
@Override
public String[] getStepDescriptions() {
return computeFixSet().isEmpty() ? new String[0] : new String[] { LoopConversion_Description };
}
@Override
public String getPreview() {
EnumSet<UseFunctionalCallFixCore> selected = computeFixSet();
EnumSet<UseFunctionalCallFixCore> shown = selected.isEmpty()
? LoopConversionService.handlers(targetFormat()) : selected;
return shown.stream().map(handler -> handler.getPreview(selected.contains(handler)))
.collect(Collectors.joining(System.lineSeparator()));
}
private LoopTargetFormat targetFormat() {
return LoopTargetFormat.fromId(optionsMap.get(LOOP_CONVERSION_TARGET_FORMAT));
}
private EnumSet<UseFunctionalCallFixCore> computeFixSet() {
// An explicit target takes precedence over legacy stream-only profile flags.
if (isEnabled(LOOP_CONVERSION_ENABLED)) {
EnumSet<UseFunctionalCallFixCore> result = LoopConversionService.handlers(targetFormat());
result.removeIf(handler -> !isEnabled(sourceOption(handler)));
return result;
}
if ((isEnabled(USEFUNCTIONALLOOP_CLEANUP) || isEnabled(USEFUNCTIONALLOOP_CLEANUP_V2))
&& !isEnabled(USEFUNCTIONALLOOP_FORMAT_FOR) && !isEnabled(USEFUNCTIONALLOOP_FORMAT_WHILE)) {
return LoopConversionService.handlers(LoopTargetFormat.STREAM);
}
return EnumSet.noneOf(UseFunctionalCallFixCore.class);
}
public static String sourceOption(UseFunctionalCallFixCore handler) {
return switch (handler) {
case LOOP, FOR_TO_ITERATOR -> LOOP_CONVERSION_FROM_ENHANCED_FOR;
case ITERATOR_LOOP, ITERATOR_TO_FOR -> LOOP_CONVERSION_FROM_ITERATOR_WHILE;
case STREAM_TO_FOR, STREAM_TO_ITERATOR -> LOOP_CONVERSION_FROM_STREAM;
case TRADITIONAL_FOR_LOOP -> LOOP_CONVERSION_FROM_CLASSIC_FOR;
};
}
}