summaryrefslogtreecommitdiff
path: root/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
blob: 565f80ac01cecfb71a19aa696e7feb63a94616a0 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package com.intellij.structuralsearch.impl.matcher;

import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator;
import com.intellij.dupLocator.iterators.NodeIterator;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.structuralsearch.StructuralSearchProfile;
import com.intellij.structuralsearch.StructuralSearchUtil;
import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler;
import com.intellij.structuralsearch.impl.matcher.handlers.SimpleHandler;
import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler;
import com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.List;

/**
 * Class to hold compiled pattern information
 */
public abstract class CompiledPattern {
  public static final String ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME = "__class_unmatched__";
  private SearchScope scope;
  private NodeIterator nodes;
  private MatchingStrategy strategy;
  private PsiElement targetNode;
  private int optionsHashStamp;
  private int nodeCount;

  // @todo support this property during matching (how many nodes should be advanced)
  // when match is not successful (or successful partially)
  //private int advancement = 1;

  public abstract String[] getTypedVarPrefixes();
  public abstract boolean isTypedVar(String str);

  public void setTargetNode(final PsiElement element) {
    targetNode = element;
  }

  public PsiElement getTargetNode() {
    return targetNode;
  }

  public int getOptionsHashStamp() {
    return optionsHashStamp;
  }

  public void setOptionsHashStamp(final int optionsHashStamp) {
    this.optionsHashStamp = optionsHashStamp;
  }

  public static final Key<Object> HANDLER_KEY = Key.create("ss.handler");

  public MatchingStrategy getStrategy() {
    return strategy;
  }

  public void setStrategy(MatchingStrategy strategy) {
    this.strategy = strategy;
  }

  public int getNodeCount() {
    return nodeCount;
  }

  public NodeIterator getNodes() {
    return nodes;
  }

  public void setNodes(List<PsiElement> elements) {
    this.nodes = new ArrayBackedNodeIterator(PsiUtilCore.toPsiElementArray(elements));
    this.nodeCount = elements.size();
  }

  public boolean isTypedVar(final PsiElement element) {
    return element!=null && isTypedVar( element.getText() );
  }

  public boolean isRealTypedVar(PsiElement element) {
    if (element!=null && element.getTextLength()>0) {
      String str = getTypedVarString(element);
      if (str.length()==0) {
        return false;
      }
      return isTypedVar( str );
    } else {
      return false;
    }
  }

  public String getTypedVarString(PsiElement element) {
    final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(element);
    if (profile == null) {
      return element.getText();
    }
    return profile.getTypedVarString(element);
  }

  private final HashMap<Object,MatchingHandler> handlers = new HashMap<Object,MatchingHandler>();

  public MatchingHandler getHandlerSimple(PsiElement node) {
    return handlers.get(node);
  }

  private PsiElement last;
  private MatchingHandler lastHandler;

  public MatchingHandler getHandler(PsiElement node) {
    if (node==last) {
      return lastHandler;
    }
    MatchingHandler handler = handlers.get(node);

    if (handler==null) {
      handler = new SimpleHandler();
      setHandler(node,handler);
    }

    last = node;
    lastHandler = handler;

    return handler;
  }

  public MatchingHandler getHandler(String name) {
    return handlers.get(name);
  }

  public void setHandler(PsiElement node, MatchingHandler handler) {
    last = null;
    handlers.put(node,handler);
  }

  public SubstitutionHandler createSubstitutionHandler(
    String name, String compiledName, boolean target,int minOccurs, int maxOccurs, boolean greedy) {

    SubstitutionHandler handler = (SubstitutionHandler) handlers.get(compiledName);
    if (handler != null) return handler;

    handler = doCreateSubstitutionHandler(name, target, minOccurs, maxOccurs, greedy);

    handlers.put(compiledName,handler);

    return handler;
  }

  protected SubstitutionHandler doCreateSubstitutionHandler(String name, boolean target, int minOccurs, int maxOccurs, boolean greedy) {
    return new SubstitutionHandler(name, target, minOccurs, maxOccurs, greedy);
  }

  public SearchScope getScope() {
    return scope;
  }

  public void setScope(SearchScope scope) {
    this.scope = scope;
  }

  public void clearHandlers() {
    handlers.clear();
    last = null;
    lastHandler = null;
  }

  void clearHandlersState() {
    for (final MatchingHandler h : handlers.values()) {
      if (h != null) h.reset();
    }
  }

  public boolean isToResetHandler(PsiElement element) {
    return true;
  }

  @Nullable
  public String getAlternativeTextToMatch(PsiElement node, String previousText) {
    return null;
  }
}