summaryrefslogtreecommitdiff
path: root/platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java')
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java186
1 files changed, 186 insertions, 0 deletions
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java b/platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java
new file mode 100644
index 000000000000..7a38ddb2ea65
--- /dev/null
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/inspection/highlightTemplate/SSBasedInspection.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.structuralsearch.inspection.highlightTemplate;
+
+import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInspection.*;
+import com.intellij.dupLocator.iterators.CountingNodeIterator;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.profile.codeInspection.InspectionProfileManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.structuralsearch.MatchResult;
+import com.intellij.structuralsearch.Matcher;
+import com.intellij.structuralsearch.SSRBundle;
+import com.intellij.structuralsearch.StructuralSearchException;
+import com.intellij.structuralsearch.impl.matcher.MatchContext;
+import com.intellij.structuralsearch.impl.matcher.MatcherImpl;
+import com.intellij.structuralsearch.impl.matcher.filters.LexicalNodesFilter;
+import com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator;
+import com.intellij.structuralsearch.plugin.replace.ReplacementInfo;
+import com.intellij.structuralsearch.plugin.replace.impl.Replacer;
+import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
+import com.intellij.structuralsearch.plugin.ui.Configuration;
+import com.intellij.structuralsearch.plugin.ui.ConfigurationManager;
+import com.intellij.structuralsearch.plugin.ui.SearchContext;
+import com.intellij.util.PairProcessor;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+import javax.swing.*;
+import java.util.*;
+
+/**
+ * @author cdr
+ */
+public class SSBasedInspection extends LocalInspectionTool {
+ static final String SHORT_NAME = "SSBasedInspection";
+ private List<Configuration> myConfigurations = new ArrayList<Configuration>();
+ private Set<String> myProblemsReported = new HashSet<String>(1);
+
+ public void writeSettings(@NotNull Element node) throws WriteExternalException {
+ ConfigurationManager.writeConfigurations(node, myConfigurations, Collections.<Configuration>emptyList());
+ }
+
+ public void readSettings(@NotNull Element node) throws InvalidDataException {
+ myProblemsReported.clear();
+ myConfigurations.clear();
+ ConfigurationManager.readConfigurations(node, myConfigurations, new ArrayList<Configuration>());
+ }
+
+ @NotNull
+ public String getGroupDisplayName() {
+ return GENERAL_GROUP_NAME;
+ }
+
+ @NotNull
+ public String getDisplayName() {
+ return SSRBundle.message("SSRInspection.display.name");
+ }
+
+ @NotNull
+ @NonNls
+ public String getShortName() {
+ return SHORT_NAME;
+ }
+
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+ final MatcherImpl.CompiledOptions compiledOptions =
+ SSBasedInspectionCompiledPatternsCache.getCompiledOptions(holder.getProject());
+
+ if (compiledOptions == null) return super.buildVisitor(holder, isOnTheFly);
+
+ return new PsiElementVisitor() {
+ final List<Pair<MatchContext,Configuration>> contexts = compiledOptions.getMatchContexts();
+ final Matcher matcher = new Matcher(holder.getManager().getProject());
+ final PairProcessor<MatchResult, Configuration> processor = new PairProcessor<MatchResult, Configuration>() {
+ public boolean process(MatchResult matchResult, Configuration configuration) {
+ PsiElement element = matchResult.getMatch();
+ String name = configuration.getName();
+ LocalQuickFix fix = createQuickFix(holder.getManager().getProject(), matchResult, configuration);
+ holder.registerProblem(
+ holder.getManager().createProblemDescriptor(element, name, fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)
+ );
+ return true;
+ }
+ };
+
+ @Override
+ public void visitElement(PsiElement element) {
+ if (LexicalNodesFilter.getInstance().accepts(element)) return;
+ final SsrFilteringNodeIterator matchedNodes = new SsrFilteringNodeIterator(element);
+ for (Pair<MatchContext, Configuration> pair : contexts) {
+ Configuration configuration = pair.second;
+ MatchContext context = pair.first;
+
+ if (MatcherImpl.checkIfShouldAttemptToMatch(context, matchedNodes)) {
+ final int nodeCount = context.getPattern().getNodeCount();
+ try {
+ matcher.processMatchesInElement(context, configuration, new CountingNodeIterator(nodeCount, matchedNodes), processor);
+ }
+ catch (StructuralSearchException e) {
+ if (myProblemsReported.add(configuration.getName())) { // don't overwhelm the user with messages
+ Notifications.Bus.notify(new Notification(SSRBundle.message("structural.search.title"),
+ SSRBundle.message("template.problem", configuration.getName()),
+ e.getMessage(),
+ NotificationType.ERROR), element.getProject());
+ }
+ }
+ matchedNodes.reset();
+ }
+ }
+ }
+ };
+ }
+
+ private static LocalQuickFix createQuickFix(final Project project, final MatchResult matchResult, final Configuration configuration) {
+ if (!(configuration instanceof ReplaceConfiguration)) return null;
+ ReplaceConfiguration replaceConfiguration = (ReplaceConfiguration)configuration;
+ final Replacer replacer = new Replacer(project, replaceConfiguration.getOptions());
+ final ReplacementInfo replacementInfo = replacer.buildReplacement(matchResult);
+
+ return new LocalQuickFix() {
+ @NotNull
+ public String getName() {
+ return SSRBundle.message("SSRInspection.replace.with", replacementInfo.getReplacement());
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ PsiElement element = descriptor.getPsiElement();
+ if (element != null && FileModificationService.getInstance().preparePsiElementsForWrite(element)) {
+ replacer.replace(replacementInfo);
+ }
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return SSRBundle.message("SSRInspection.family.name");
+ }
+ };
+ }
+
+ @Nullable
+ public JComponent createOptionsPanel() {
+ return new SSBasedInspectionOptions(myConfigurations){
+ public void configurationsChanged(final SearchContext searchContext) {
+ super.configurationsChanged(searchContext);
+ SSBasedInspectionCompiledPatternsCache.precompileConfigurations(searchContext.getProject(), SSBasedInspection.this);
+ InspectionProfileManager.getInstance().fireProfileChanged(null);
+ }
+ }.getComponent();
+ }
+
+ @TestOnly
+ public void setConfigurations(final List<Configuration> configurations, final Project project) {
+ myConfigurations = configurations;
+ SSBasedInspectionCompiledPatternsCache.setCompiledOptions(project, configurations);
+ }
+
+ public List<Configuration> getConfigurations() {
+ return myConfigurations;
+ }
+}