mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[codeInsight] Select inspection profile for code cleanup on save
#IJPL-60378 Fixed GitOrigin-RevId: aa2d004c7a62183c6a3763c0b493a13332522e24
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ddf360b575
commit
fd0d3ebfc7
@@ -520,6 +520,8 @@ actions.on.save.page.popup.title.arrangement.settings=Open Arrangement Settings
|
||||
actions.on.save.page.checkbox.run.code.cleanup=Run code cleanup
|
||||
actions.on.save.page.code.cleanup.comment=Applies fixes from the code cleanup inspections
|
||||
actions.on.save.page.link.configure.inspections=Configure inspections\u2026
|
||||
actions.on.save.page.code.cleanup.project.profile=Project Profile
|
||||
actions.on.save.page.code.cleanup.profile=Profile: {0}
|
||||
|
||||
non.ascii.chars.inspection.non.ascii.top.label=Report Non-ASCII Characters In:
|
||||
non.ascii.chars.inspection.option.files.containing.bom.checkbox=Report files starting with a BOM
|
||||
|
||||
@@ -2531,6 +2531,7 @@ f:com.intellij.codeInsight.actions.CodeCleanupCodeProcessor
|
||||
- <init>(com.intellij.codeInsight.actions.AbstractLayoutCodeProcessor,com.intellij.openapi.editor.SelectionModel):V
|
||||
- <init>(com.intellij.openapi.project.Project,com.intellij.psi.PsiFile[],java.lang.Runnable,Z):V
|
||||
- s:getProgressText():java.lang.String
|
||||
- setProfile(com.intellij.codeInspection.ex.InspectionProfileImpl):V
|
||||
com.intellij.codeInsight.actions.DirectoryFormattingOptions
|
||||
- com.intellij.codeInsight.actions.ReformatFilesOptions
|
||||
- a:isIncludeSubdirectories():Z
|
||||
@@ -2784,7 +2785,16 @@ f:com.intellij.codeInsight.actions.onSave.CodeCleanupOnSaveActionInfo
|
||||
- <init>(com.intellij.ide.actionsOnSave.ActionOnSaveContext):V
|
||||
- getActionLinks():java.util.List
|
||||
- getComment():com.intellij.ide.actionsOnSave.ActionOnSaveComment
|
||||
- getDropDownLinks():java.util.List
|
||||
- s:isCodeCleanupOnSaveEnabled(com.intellij.openapi.project.Project):Z
|
||||
f:com.intellij.codeInsight.actions.onSave.CodeCleanupOnSaveOptions
|
||||
- com.intellij.openapi.components.PersistentStateComponent
|
||||
- PROFILE:java.lang.String
|
||||
- <init>(com.intellij.openapi.project.Project):V
|
||||
- getInspectionProfile():com.intellij.codeInspection.ex.InspectionProfileImpl
|
||||
- s:getInstance(com.intellij.openapi.project.Project):com.intellij.codeInsight.actions.onSave.CodeCleanupOnSaveOptions
|
||||
- getState():com.intellij.codeInsight.actions.onSave.CodeCleanupOnSaveOptions
|
||||
- loadState(com.intellij.codeInsight.actions.onSave.CodeCleanupOnSaveOptions):V
|
||||
a:com.intellij.codeInsight.actions.onSave.FormatOnSaveActionInfoBase
|
||||
- com.intellij.ide.actionsOnSave.ActionOnSaveInfo
|
||||
- pa:addApplicableFileTypes(java.util.Collection):V
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.codeInsight.actions;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
@@ -19,6 +20,7 @@ import java.util.concurrent.FutureTask;
|
||||
public final class CodeCleanupCodeProcessor extends AbstractLayoutCodeProcessor {
|
||||
|
||||
private SelectionModel mySelectionModel = null;
|
||||
private InspectionProfileImpl myProfile = null;
|
||||
|
||||
public CodeCleanupCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) {
|
||||
super(previousProcessor, CodeInsightBundle.message("command.cleanup.code"), getProgressText());
|
||||
@@ -42,11 +44,19 @@ public final class CodeCleanupCodeProcessor extends AbstractLayoutCodeProcessor
|
||||
return new FutureTask<>(() -> {
|
||||
if (!file.isValid()) return false;
|
||||
Collection<TextRange> ranges = getRanges(file, processChangedTextOnly);
|
||||
GlobalInspectionContextBase.cleanupElements(myProject, null, descriptor -> isInRanges(ranges, descriptor), file);
|
||||
if (myProfile == null) {
|
||||
GlobalInspectionContextBase.cleanupElements(myProject, null, descriptor -> isInRanges(ranges, descriptor), file);
|
||||
} else {
|
||||
GlobalInspectionContextBase.cleanupElements(myProject, null, descriptor -> isInRanges(ranges, descriptor), myProfile, file);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void setProfile(InspectionProfileImpl profile) {
|
||||
myProfile = profile;
|
||||
}
|
||||
|
||||
private Collection<TextRange> getRanges(@NotNull PsiFile file, boolean processChangedTextOnly) {
|
||||
if (mySelectionModel != null) {
|
||||
return getSelectedRanges(mySelectionModel);
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.actions.onSave;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.actionsOnSave.ActionOnSaveComment;
|
||||
import com.intellij.ide.actionsOnSave.ActionOnSaveContext;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable;
|
||||
import com.intellij.ui.components.ActionLink;
|
||||
import com.intellij.ui.components.DropDownLink;
|
||||
import com.intellij.ui.dsl.listCellRenderer.BuilderKt;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class CodeCleanupOnSaveActionInfo extends ActionOnSaveInfoBase {
|
||||
private static final String CODE_CLEANUP_ON_SAVE_PROPERTY = "code.cleanup.on.save";
|
||||
private static final boolean CODE_CLEANUP_ON_SAVE_DEFAULT = false;
|
||||
private String myProfile;
|
||||
|
||||
public static boolean isCodeCleanupOnSaveEnabled(@NotNull Project project) {
|
||||
return PropertiesComponent.getInstance(project).getBoolean(CODE_CLEANUP_ON_SAVE_PROPERTY, CODE_CLEANUP_ON_SAVE_DEFAULT);
|
||||
@@ -25,6 +38,7 @@ public final class CodeCleanupOnSaveActionInfo extends ActionOnSaveInfoBase {
|
||||
CodeInsightBundle.message("actions.on.save.page.checkbox.run.code.cleanup"),
|
||||
CODE_CLEANUP_ON_SAVE_PROPERTY,
|
||||
CODE_CLEANUP_ON_SAVE_DEFAULT);
|
||||
myProfile = CodeCleanupOnSaveOptions.getInstance(getProject()).PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,4 +51,82 @@ public final class CodeCleanupOnSaveActionInfo extends ActionOnSaveInfoBase {
|
||||
return List.of(createGoToPageInSettingsLink(CodeInsightBundle.message("actions.on.save.page.link.configure.inspections"),
|
||||
InspectionToolsConfigurable.ID));
|
||||
}
|
||||
}
|
||||
|
||||
private record ProfileOption(@NlsSafe @Nullable String profileName) {}
|
||||
|
||||
@Override
|
||||
public @NotNull List<? extends DropDownLink<?>> getDropDownLinks() {
|
||||
List<ProfileOption> profiles = new ArrayList<>();
|
||||
|
||||
// Project Profile
|
||||
profiles.add(new ProfileOption(null));
|
||||
|
||||
// Stored in project
|
||||
List<ProfileOption> projectProfiles = ContainerUtil.map(
|
||||
InspectionProfileManager.getInstance(getProject()).getProfiles(),
|
||||
p -> new ProfileOption(p.getDisplayName())
|
||||
);
|
||||
profiles.addAll(projectProfiles);
|
||||
|
||||
// Stored in IDE
|
||||
List<ProfileOption> ideProfiles = ContainerUtil.map(
|
||||
InspectionProfileManager.getInstance().getProfiles(),
|
||||
p -> new ProfileOption(p.getDisplayName())
|
||||
);
|
||||
profiles.addAll(ideProfiles);
|
||||
|
||||
// Separators
|
||||
final var separators = new HashMap<ProfileOption, String>();
|
||||
if (!projectProfiles.isEmpty()) {
|
||||
separators.put(projectProfiles.get(0), IdeBundle.message("separator.scheme.stored.in", IdeBundle.message("scheme.project")));
|
||||
}
|
||||
if (!ideProfiles.isEmpty()) {
|
||||
separators.put(ideProfiles.get(0), IdeBundle.message("separator.scheme.stored.in", IdeBundle.message("scheme.project")));
|
||||
}
|
||||
|
||||
var selectedOption = getSelectedProfile(profiles);
|
||||
|
||||
DropDownLink<ProfileOption> inspectionProfileLink = new DropDownLink<>(
|
||||
selectedOption,
|
||||
profiles,
|
||||
option -> {
|
||||
myProfile = option.profileName;
|
||||
},
|
||||
true) {
|
||||
|
||||
@Override
|
||||
protected @Nls @NotNull String itemToString(ProfileOption item) {
|
||||
if (item.profileName == null) return CodeInsightBundle.message("actions.on.save.page.code.cleanup.project.profile");
|
||||
return CodeInsightBundle.message("actions.on.save.page.code.cleanup.profile", item.profileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListCellRenderer<? super ProfileOption> createRenderer() {
|
||||
return BuilderKt.groupedTextListCellRenderer(p -> {
|
||||
if (p.profileName == null) return CodeInsightBundle.message("actions.on.save.page.code.cleanup.project.profile");
|
||||
return p.profileName();
|
||||
}, p -> separators.getOrDefault(p, null));
|
||||
}
|
||||
};
|
||||
|
||||
return List.of(inspectionProfileLink);
|
||||
}
|
||||
|
||||
private ProfileOption getSelectedProfile(List<ProfileOption> profiles) {
|
||||
if (myProfile == null) return profiles.get(0);
|
||||
final var selected = ContainerUtil.find(profiles, p -> p != null && Objects.equals(p.profileName, myProfile));
|
||||
if (selected == null) return profiles.get(0); // If the profile has been deleted, default to project profile
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified() {
|
||||
return super.isModified() || !Objects.equals(myProfile, CodeCleanupOnSaveOptions.getInstance(getProject()).PROFILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply() {
|
||||
super.apply();
|
||||
CodeCleanupOnSaveOptions.getInstance(getProject()).PROFILE = myProfile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.actions.onSave;
|
||||
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(name = "CodeCleanupOnSaveOptions", storages = @Storage(StoragePathMacros.WORKSPACE_FILE))
|
||||
public final class CodeCleanupOnSaveOptions implements PersistentStateComponent<CodeCleanupOnSaveOptions> {
|
||||
public static @NotNull CodeCleanupOnSaveOptions getInstance(@NotNull Project project) { return project.getService(CodeCleanupOnSaveOptions.class); }
|
||||
|
||||
private Project myProject;
|
||||
private static Logger LOG = Logger.getInstance(CodeCleanupOnSaveOptions.class);
|
||||
public @Nullable String PROFILE = null;
|
||||
|
||||
public CodeCleanupOnSaveOptions(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public InspectionProfileImpl getInspectionProfile() {
|
||||
final var projectProfileManager = InspectionProfileManager.getInstance(myProject);
|
||||
if (PROFILE == null) return projectProfileManager.getCurrentProfile();
|
||||
|
||||
final var projectProfile = ContainerUtil.find(
|
||||
projectProfileManager.getProfiles(),
|
||||
p -> Objects.equals(p.getName(), PROFILE)
|
||||
);
|
||||
if (projectProfile != null) return projectProfile;
|
||||
|
||||
final var appProfile = ContainerUtil.find(
|
||||
InspectionProfileManager.getInstance().getProfiles(),
|
||||
p -> Objects.equals(p.getName(), PROFILE)
|
||||
);
|
||||
if (appProfile != null) return projectProfile;
|
||||
|
||||
LOG.warn("Can't find profile " + PROFILE + ". Using project profile instead.");
|
||||
return projectProfileManager.getCurrentProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeCleanupOnSaveOptions getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull CodeCleanupOnSaveOptions state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,7 @@ internal class FormatOnSaveAction : ActionOnSave() {
|
||||
|
||||
if (CodeCleanupOnSaveActionInfo.isCodeCleanupOnSaveEnabled(project) && !isDumb(project)) {
|
||||
processor = CodeCleanupCodeProcessor(processor)
|
||||
processor.setProfile(CodeCleanupOnSaveOptions.getInstance(project).getInspectionProfile())
|
||||
}
|
||||
|
||||
// This guarantees that per-file undo chain won't break and there won't be the "Following files affected by this action have been already changed" modal error dialog.
|
||||
|
||||
Reference in New Issue
Block a user