summaryrefslogtreecommitdiff
path: root/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java
blob: 80f0c7b8ce0d35228d92e8a3202e7b26daedf59e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.intellij.structuralsearch.plugin.ui;

import com.intellij.notification.NotificationGroup;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.structuralsearch.*;
import com.intellij.structuralsearch.impl.matcher.MatchResultImpl;
import com.intellij.structuralsearch.plugin.StructuralSearchPlugin;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.Usage;
import com.intellij.usages.UsageInfo2UsageAdapter;
import com.intellij.util.Alarm;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;

/**
 * Created by IntelliJ IDEA.
 * User: Maxim.Mossienko
 * Date: Mar 15, 2004
 * Time: 4:49:07 PM
 * To change this template use File | Settings | File Templates.
 */
public class SearchCommand {
  protected UsageViewContext context;
  private MatchingProcess process;
  protected Project project;

  public SearchCommand(Project _project, UsageViewContext _context) {
    project = _project;
    context = _context;
  }

  public void findUsages(final Processor<Usage> processor) {
    final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();

    final MatchResultSink sink = new MatchResultSink() {
      int count;

      public void setMatchingProcess(MatchingProcess _process) {
        process = _process;
        findStarted();
      }

      public void processFile(PsiFile element) {
        final VirtualFile virtualFile = element.getVirtualFile();
        if (virtualFile != null)
          progress.setText(SSRBundle.message("looking.in.progress.message", virtualFile.getPresentableName()));
      }

      public void matchingFinished() {
        if (project.isDisposed()) return;
        findEnded();
        progress.setText(SSRBundle.message("found.progress.message", count));
      }

      public ProgressIndicator getProgressIndicator() {
        return progress;
      }

      public void newMatch(MatchResult result) {
        UsageInfo info;

        if (MatchResult.MULTI_LINE_MATCH.equals(result.getName())) {
          int start = -1;
          int end = -1;
          PsiElement parent = result.getMatchRef().getElement().getParent();

          for (final MatchResult matchResult : ((MatchResultImpl)result).getMatches()) {
            PsiElement el = matchResult.getMatchRef().getElement();
            final int elementStart = el.getTextRange().getStartOffset();

            if (start == -1 || start > elementStart) {
              start = elementStart;
            }
            final int newend = elementStart + el.getTextLength();

            if (newend > end) {
              end = newend;
            }
          }

          final int parentStart = parent.getTextRange().getStartOffset();
          int startOffset = start - parentStart;
          info = new UsageInfo(parent, startOffset, end - parentStart);
        }
        else {
          PsiElement element = result.getMatch();
          if (element instanceof PsiNameIdentifierOwner) {
            element = ObjectUtils.notNull(((PsiNameIdentifierOwner)element).getNameIdentifier(), element);
          }
          info = new UsageInfo(element, result.getStart(), result.getEnd() == -1 ? element.getTextLength() : result.getEnd());
        }

        Usage usage = new UsageInfo2UsageAdapter(info);
        processor.process(usage);
        foundUsage(result, usage);
        ++count;
      }
    };

    try {
      new Matcher(project).findMatches(sink, context.getConfiguration().getMatchOptions());
    }
    catch (final StructuralSearchException e) {
      final Alarm alarm = new Alarm();
      alarm.addRequest(
        new Runnable() {
          @Override
          public void run() {
            NotificationGroup.toolWindowGroup("Structural Search", ToolWindowId.FIND)
              .createNotification(SSRBundle.message("problem", e.getMessage()), MessageType.ERROR).notify(project);
          }
        },
        100, ModalityState.NON_MODAL
      );
    }
  }

  public void stopAsyncSearch() {
    if (process!=null) process.stop();
  }

  protected void findStarted() {
    StructuralSearchPlugin.getInstance(project).setSearchInProgress(true);
  }

  protected void findEnded() {
    StructuralSearchPlugin.getInstance(project).setSearchInProgress(false);
  }

  protected void foundUsage(MatchResult result, Usage usage) {
  }
}