SSR: add/remove inspections

GitOrigin-RevId: 428fd9accc1bd3bf571b25615353816475bab0f2
This commit is contained in:
Bas Leijdekkers
2020-01-02 22:03:38 +00:00
committed by intellij-monorepo-bot
parent 8d2428db65
commit a7da088986
10 changed files with 274 additions and 60 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
@@ -589,6 +589,10 @@ public class InspectionProfileImpl extends NewInspectionProfile {
public void removeTool(@NotNull InspectionToolWrapper inspectionTool) {
String shortName = inspectionTool.getShortName();
removeTool(shortName);
}
public void removeTool(@NotNull String shortName) {
myTools.remove(shortName);
HighlightDisplayKey.unregister(shortName);
}
@@ -0,0 +1,19 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.profile.codeInspection.ui;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author Bas Leijdekkers
*/
public abstract class InspectionProfileActionProvider {
public static final ExtensionPointName<InspectionProfileActionProvider> EP_NAME =
ExtensionPointName.create("com.intellij.inspectionProfileActionProvider");
@NotNull
public abstract List<AnAction> getActions(SingleInspectionProfilePanel panel);
}
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.profile.codeInspection.ui;
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.*;
import com.intellij.icons.AllIcons;
@@ -21,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.SchemeState;
import com.intellij.openapi.options.ex.Settings;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
@@ -28,6 +30,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.profile.ProfileChangeAdapter;
import com.intellij.profile.codeInspection.BaseInspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
@@ -107,8 +110,19 @@ public class SingleInspectionProfilePanel extends JPanel {
super(new BorderLayout());
myProjectProfileManager = projectProfileManager;
myProfile = profile;
final Project project = projectProfileManager.getProject();
// to ensure that profile initialized with proper project
myProfile.initInspectionTools(projectProfileManager.getProject());
myProfile.initInspectionTools(project);
project.getMessageBus().connect(myDisposable).subscribe(ProfileChangeAdapter.TOPIC, new ProfileChangeAdapter() {
@Override
public void profileChanged(@Nullable InspectionProfile profile) {
if (myProfile == profile) {
initToolStates();
filterTree();
}
}
});
}
public boolean differsFromDefault() {
@@ -444,6 +458,11 @@ public class SingleInspectionProfilePanel extends JPanel {
postProcessModification();
}
});
for (InspectionProfileActionProvider provider : InspectionProfileActionProvider.EP_NAME.getExtensionList()) {
for (AnAction action : provider.getActions(this)) {
actions.add(action);
}
}
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("SingleInspectionProfile", actions, true);
actionToolbar.setTargetComponent(this);
@@ -914,6 +933,25 @@ public class SingleInspectionProfilePanel extends JPanel {
return myProfile;
}
public InspectionToolWrapper<?, ?> getSelectedTool() {
InspectionConfigTreeNode.Tool node = myTreeTable.getStrictlySelectedToolNode();
if (node == null) return null;
return node.getDefaultDescriptor().getToolWrapper();
}
public void removeSelectedRow() {
final InspectionConfigTreeNode.Tool node = myTreeTable.getStrictlySelectedToolNode();
if (node != null) {
getExpandedNodes(myProfile).saveVisibleState(myTreeTable.getTree());
final TreePath path = myTreeTable.getTree().getSelectionPath();
assert path != null;
final TreePath newPath = path.getParentPath().pathByAddingChild(node.getPreviousNode());
myTreeTable.removeSelectedPath(path);
myTreeTable.addSelectedPath(newPath);
restoreTreeState();
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(700, 500);
@@ -1019,7 +1057,7 @@ public class SingleInspectionProfilePanel extends JPanel {
public boolean isModified() {
if (myTreeTable == null) return false;
if (myModified) return true;
if (myProfile.isChanged()) return true;
if (myProfile.isChanged() || myProfile.getSchemeState() == SchemeState.POSSIBLY_CHANGED) return true;
if (myProfile.getSource().isProjectLevel() != myProfile.isProjectLevel()) return true;
if (!Comparing.strEqual(myProfile.getSource().getName(), myProfile.getName())) return true;
if (!Arrays.equals(myInitialScopesOrder, myProfile.getScopesOrder())) return true;
@@ -223,6 +223,7 @@
</extensionPoint>
<extensionPoint name="inspectionToolProvider" interface="com.intellij.codeInspection.InspectionToolProvider" dynamic="true"/>
<extensionPoint name="codeInspection.InspectionExtension" interface="com.intellij.codeInspection.lang.InspectionExtensionsFactory" dynamic="true"/>
<extensionPoint name="inspectionProfileActionProvider" interface="com.intellij.profile.codeInspection.ui.InspectionProfileActionProvider" dynamic="true"/>
<extensionPoint name="liveTemplateContext" interface="com.intellij.codeInsight.template.TemplateContextType" dynamic="true"/>
<extensionPoint name="liveTemplateMacro" interface="com.intellij.codeInsight.template.Macro" dynamic="true"/>
@@ -24,6 +24,7 @@
<codeInsight.linkHandler prefix="#ssr_edit_filters/" handlerClass="com.intellij.structuralsearch.plugin.ui.filters.FilterTooltipLinkHandler"/>
<daemon.highlightInfoFilter implementation="com.intellij.structuralsearch.plugin.ui.StructuralSearchHighlightInfoFilter"/>
<postStartupActivity implementation="com.intellij.structuralsearch.inspection.InspectionProvider"/>
<inspectionProfileActionProvider implementation="com.intellij.structuralsearch.inspection.StructuralSearchProfileActionProvider"/>
</extensions>
<actions>
@@ -1,17 +1,15 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.inspection;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection;
import com.intellij.structuralsearch.inspection.highlightTemplate.StructuralSearchFakeInspection;
import com.intellij.structuralsearch.plugin.ui.Configuration;
import org.jetbrains.annotations.NotNull;
@@ -25,12 +23,11 @@ public class InspectionProvider implements StartupActivity.DumbAware {
@Override
public void runActivity(@NotNull Project project) {
if (!Registry.is("ssr.separate.inspections")) return;
addStructuralSearchInspectionsToProfiles(ApplicationInspectionProfileManager.getInstanceImpl(), project);
addStructuralSearchInspectionsToProfiles(ProjectInspectionProfileManager.getInstance(project), project);
addStructuralSearchInspectionsToProfiles(InspectionProfileManager.getInstance(), project);
addStructuralSearchInspectionsToProfiles(InspectionProfileManager.getInstance(project), project);
}
private static void addStructuralSearchInspectionsToProfiles(InspectionProfileManager profileManager, @NotNull Project project) {
final InspectionProfileImpl baseProfile = InspectionProfileKt.getBASE_PROFILE();
for (InspectionProfileImpl profile : profileManager.getProfiles()) {
final InspectionToolWrapper<?, ?> wrapper = profile.getInspectionTool(SSBasedInspection.SHORT_NAME, project);
assert wrapper != null;
@@ -38,48 +35,38 @@ public class InspectionProvider implements StartupActivity.DumbAware {
final HighlightDisplayKey key = HighlightDisplayKey.find(SSBasedInspection.SHORT_NAME);
final boolean enabled = profile.isToolEnabled(key);
for (Configuration configuration : ssBasedInspection.getConfigurations()) {
final UUID uuid = configuration.getUuid();
final InspectionToolWrapper<?, ?> toolWrapper;
if (uuid == null) {
configuration.setUuid(UUID.randomUUID());
toolWrapper = null;
}
else {
toolWrapper = profile.getInspectionTool(configuration.getUuid().toString(), project);
}
if (toolWrapper == null) {
final LocalInspectionToolWrapper wrapped = new StructuralSearchInspectionToolWrapper(configuration);
profile.addTool(project, wrapped, null);
profile.setToolEnabled(configuration.getUuid().toString(), enabled);
baseProfile.addTool(project, wrapped, null);
}
addConfigurationToProfile(project, profile, configuration, enabled);
}
}
}
private static class StructuralSearchInspectionToolWrapper extends LocalInspectionToolWrapper {
StructuralSearchInspectionToolWrapper(Configuration configuration) {
super(new StructuralSearchFakeInspection(configuration.getName(), configuration.getUuid()));
}
private StructuralSearchInspectionToolWrapper(@NotNull LocalInspectionTool tool) {
super(tool);
}
public static void addConfigurationToProfile(@NotNull Project project,
InspectionProfileImpl profile,
Configuration configuration) {
addConfigurationToProfile(project, profile, configuration, true);
}
@NotNull
@Override
public LocalInspectionToolWrapper createCopy() {
return new StructuralSearchInspectionToolWrapper(new StructuralSearchFakeInspection((StructuralSearchFakeInspection)getTool()));
private static void addConfigurationToProfile(@NotNull Project project,
InspectionProfileImpl profile,
Configuration configuration, boolean enabled) {
final UUID uuid = configuration.getUuid();
final InspectionToolWrapper<?, ?> toolWrapper;
if (uuid == null) {
configuration.setUuid(UUID.randomUUID());
toolWrapper = null;
}
else {
toolWrapper = profile.getInspectionTool(configuration.getUuid().toString(), project);
}
if (toolWrapper == null) {
final LocalInspectionToolWrapper wrapped = new StructuralSearchInspectionToolWrapper(configuration);
profile.addTool(project, wrapped, null);
@Override
public void initialize(@NotNull GlobalInspectionContext context) {
super.initialize(context);
final InspectionProfileImpl profile = ((GlobalInspectionContextBase)context).getCurrentProfile();
final InspectionToolWrapper<?, ?> tool = profile.getInspectionTool(SSBasedInspection.SHORT_NAME, context.getProject());
assert tool != null;
final SSBasedInspection inspection = (SSBasedInspection)tool.getTool();
inspection.setSessionProfile(profile);
// enable inspection even when profile is locked, because either:
// - user just added this inspection explicitly
// - or inspection was just imported from enabled old SSR inspection
profile.setToolEnabled(configuration.getUuid().toString(), enabled);
}
}
}
@@ -0,0 +1,46 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.inspection;
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection;
import com.intellij.structuralsearch.inspection.highlightTemplate.StructuralSearchFakeInspection;
import com.intellij.structuralsearch.plugin.ui.Configuration;
import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
*/
public class StructuralSearchInspectionToolWrapper extends LocalInspectionToolWrapper {
StructuralSearchInspectionToolWrapper(Configuration configuration) {
super(new StructuralSearchFakeInspection(configuration.getName(), configuration.getUuid()));
}
private StructuralSearchInspectionToolWrapper(@NotNull LocalInspectionTool tool) {
super(tool);
}
@NotNull
@Override
public LocalInspectionToolWrapper createCopy() {
return new StructuralSearchInspectionToolWrapper(new StructuralSearchFakeInspection((StructuralSearchFakeInspection)getTool()));
}
@Override
public void initialize(@NotNull GlobalInspectionContext context) {
super.initialize(context);
final InspectionProfileImpl profile = ((GlobalInspectionContextBase)context).getCurrentProfile();
final InspectionToolWrapper<?, ?> tool = profile.getInspectionTool(SSBasedInspection.SHORT_NAME, context.getProject());
assert tool != null;
final SSBasedInspection inspection = (SSBasedInspection)tool.getTool();
inspection.setSessionProfile(profile);
}
public void setProfile(InspectionProfileImpl profile) {
((StructuralSearchFakeInspection)myTool).setProfile(profile);
}
}
@@ -0,0 +1,117 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.inspection;
import com.intellij.codeInspection.ex.InspectionProfileModifiableModel;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.ScopeToolState;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.profile.codeInspection.ui.InspectionProfileActionProvider;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
import com.intellij.structuralsearch.SSRBundle;
import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection;
import com.intellij.structuralsearch.plugin.ui.Configuration;
import com.intellij.structuralsearch.plugin.ui.ConfigurationManager;
import com.intellij.structuralsearch.plugin.ui.SearchContext;
import com.intellij.structuralsearch.plugin.ui.StructuralSearchDialog;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author Bas Leijdekkers
*/
public class StructuralSearchProfileActionProvider extends InspectionProfileActionProvider {
private SingleInspectionProfilePanel myProfilePanel;
@NotNull
@Override
public List<AnAction> getActions(SingleInspectionProfilePanel panel) {
if (!Registry.is("ssr.separate.inspections")) return Collections.emptyList();
final InspectionProfileModifiableModel profile = panel.getProfile();
for (ScopeToolState tool : profile.getAllTools()) {
final InspectionToolWrapper<?, ?> wrapper = tool.getTool();
if (wrapper instanceof StructuralSearchInspectionToolWrapper) {
((StructuralSearchInspectionToolWrapper)wrapper).setProfile(profile);
}
}
final DefaultActionGroup actionGroup = new DefaultActionGroup(
new AddTemplateAction(panel, false),
new AddTemplateAction(panel, true)
);
actionGroup.setPopup(true);
actionGroup.registerCustomShortcutSet(CommonShortcuts.INSERT, panel);
final Presentation presentation = actionGroup.getTemplatePresentation();
presentation.setIcon(AllIcons.General.Add);
presentation.setText("Add Structural Search && Replace Inspection");
return Arrays.asList(actionGroup, new RemoveTemplateAction(panel));
}
private static class RemoveTemplateAction extends DumbAwareAction {
private final SingleInspectionProfilePanel myPanel;
private RemoveTemplateAction(SingleInspectionProfilePanel panel) {
super("Remove Structural Search && Replace Inspection", null, AllIcons.General.Remove);
myPanel = panel;
registerCustomShortcutSet(CommonShortcuts.getDelete(), myPanel);
}
@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(myPanel.getSelectedTool() instanceof StructuralSearchInspectionToolWrapper);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final String shortName = myPanel.getSelectedTool().getShortName();
myPanel.removeSelectedRow();
final InspectionProfileModifiableModel profile = myPanel.getProfile();
profile.removeTool(shortName);
profile.getProfileManager().fireProfileChanged(profile);
}
}
private static class AddTemplateAction extends DumbAwareAction {
private final SingleInspectionProfilePanel myPanel;
private final boolean myReplace;
private AddTemplateAction(SingleInspectionProfilePanel panel, boolean replace) {
super(replace
? SSRBundle.message("SSRInspection.add.replace.template.button")
: SSRBundle.message("SSRInspection.add.search.template.button"));
myPanel = panel;
myReplace = replace;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final SearchContext context = new SearchContext(e.getDataContext());
final StructuralSearchDialog dialog = new StructuralSearchDialog(context, myReplace, true);
if (!dialog.showAndGet()) return;
final InspectionProfileModifiableModel profile = myPanel.getProfile();
final Project project = e.getData(CommonDataKeys.PROJECT);
assert project != null;
final InspectionToolWrapper<?, ?> wrapper = profile.getInspectionTool(SSBasedInspection.SHORT_NAME, project);
assert wrapper != null;
final SSBasedInspection inspection = (SSBasedInspection)wrapper.getTool();
final Configuration configuration = dialog.getConfiguration();
if (!ConfigurationManager.showSaveTemplateAsDialog(inspection.getConfigurations(), configuration, project)) {
return;
}
InspectionProvider.addConfigurationToProfile(project, profile, configuration);
profile.getProfileManager().fireProfileChanged(profile);
myPanel.selectInspectionTool(configuration.getUuid().toString());
}
}
}
@@ -191,6 +191,6 @@ public class SSBasedInspection extends LocalInspectionTool {
}
public List<Configuration> getConfigurations() {
return Collections.unmodifiableList(myConfigurations);
return myConfigurations;
}
}
@@ -1,7 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.inspection.highlightTemplate;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -14,29 +15,25 @@ import java.util.UUID;
public class StructuralSearchFakeInspection extends LocalInspectionTool {
private final String myShortName;
private String name = "";
@SuppressWarnings("unused")
public StructuralSearchFakeInspection() {
myShortName = "";
}
private String myName;
private InspectionProfileImpl myProfile = null;
public StructuralSearchFakeInspection(String name, UUID uuid) {
this.name = name;
this.myName = name;
myShortName = uuid.toString();
}
public StructuralSearchFakeInspection(StructuralSearchFakeInspection copy) {
myShortName = copy.myShortName;
name = copy.name;
myName = copy.myName;
myProfile = copy.myProfile;
}
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getDisplayName() {
return name;
return myName;
}
@NotNull
@@ -61,7 +58,7 @@ public class StructuralSearchFakeInspection extends LocalInspectionTool {
@NotNull
@Override
public String[] getGroupPath() {
return new String[]{"General", "Structural Search"};
return new String[]{"Structural Search"};
}
@Nullable
@@ -69,4 +66,8 @@ public class StructuralSearchFakeInspection extends LocalInspectionTool {
public String getStaticDescription() {
return "no description provided";
}
public void setProfile(InspectionProfileImpl profile) {
myProfile = profile;
}
}