use of com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy in project intellij-community by JetBrains.
the class StructuralSearchProfileBase method compile.
@Override
public void compile(PsiElement[] elements, @NotNull final GlobalCompilingVisitor globalVisitor) {
final PsiElement topElement = elements[0].getParent();
final PsiElement element = elements.length > 1 ? topElement : elements[0];
element.accept(new MyCompilingVisitor(globalVisitor, topElement));
element.accept(new PsiRecursiveElementVisitor() {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
if (DuplocatorUtil.isIgnoredNode(element)) {
return;
}
CompiledPattern pattern = globalVisitor.getContext().getPattern();
MatchingHandler handler = pattern.getHandler(element);
if (!(handler instanceof SubstitutionHandler) && !(handler instanceof TopLevelMatchingHandler) && !(handler instanceof LightTopLevelMatchingHandler)) {
pattern.setHandler(element, new SkippingHandler(handler));
}
/*
place skipping handler under top-level handler, because when we skip top-level node we can get non top-level handler, so
depth matching won't be done!;
*/
if (handler instanceof LightTopLevelMatchingHandler) {
MatchingHandler delegate = ((LightTopLevelMatchingHandler) handler).getDelegate();
if (!(delegate instanceof SubstitutionHandler)) {
pattern.setHandler(element, new LightTopLevelMatchingHandler(new SkippingHandler(delegate)));
}
}
}
});
final Language baseLanguage = element.getContainingFile().getLanguage();
// todo: try to optimize it: too heavy strategy!
globalVisitor.getContext().getPattern().setStrategy(new MatchingStrategy() {
@Override
public boolean continueMatching(PsiElement start) {
Language language = start.getLanguage();
PsiFile file = start.getContainingFile();
if (file != null) {
Language fileLanguage = file.getLanguage();
if (fileLanguage.isKindOf(language)) {
// dialect
language = fileLanguage;
}
}
return language == baseLanguage;
}
@Override
public boolean shouldSkip(PsiElement element, PsiElement elementToMatchWith) {
return DuplocatorUtil.shouldSkip(element, elementToMatchWith);
}
});
}
use of com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy in project intellij-community by JetBrains.
the class JavaCompilingVisitor method visitCodeBlock.
@Override
public void visitCodeBlock(PsiCodeBlock block) {
myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() + 1);
MatchingStrategy strategy = null;
for (PsiElement el = block.getFirstChild(); el != null; el = el.getNextSibling()) {
if (GlobalCompilingVisitor.getFilter().accepts(el)) {
if (el instanceof PsiWhiteSpace) {
myCompilingVisitor.addLexicalNode(el);
}
} else {
el.accept(this);
if (myCompilingVisitor.getCodeBlockLevel() == 1) {
MatchingStrategy newstrategy = findStrategy(el);
final MatchingHandler matchingHandler = myCompilingVisitor.getContext().getPattern().getHandler(el);
myCompilingVisitor.getContext().getPattern().setHandler(el, new TopLevelMatchingHandler(matchingHandler));
if (strategy == null || (strategy instanceof JavaDocMatchingStrategy)) {
strategy = newstrategy;
} else {
if (strategy.getClass() != newstrategy.getClass()) {
if (!(strategy instanceof CommentMatchingStrategy)) {
throw new UnsupportedPatternException(SSRBundle.message("different.strategies.for.top.level.nodes.error.message"));
}
strategy = newstrategy;
}
}
}
}
}
if (myCompilingVisitor.getCodeBlockLevel() == 1) {
if (strategy == null) {
// this should happen only for error patterns
strategy = ExprMatchingStrategy.getInstance();
}
myCompilingVisitor.getContext().getPattern().setStrategy(strategy);
}
myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() - 1);
}
use of com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy in project intellij-community by JetBrains.
the class MatchingHandler method matchSequentially.
public boolean matchSequentially(NodeIterator nodes, NodeIterator nodes2, MatchContext context) {
final MatchingStrategy strategy = context.getPattern().getStrategy();
skipIfNecessary(nodes, nodes2, strategy);
skipIfNecessary(nodes2, nodes, strategy);
final PsiElement patternElement = nodes.current();
final MatchingHandler handler = context.getPattern().getHandler(patternElement);
if (nodes2.hasNext() && handler.match(patternElement, nodes2.current(), context)) {
nodes.advance();
final boolean shouldRewindOnMatchFailure;
if (shouldAdvanceTheMatchFor(patternElement, nodes2.current())) {
nodes2.advance();
skipIfNecessary(nodes, nodes2, strategy);
shouldRewindOnMatchFailure = true;
} else {
shouldRewindOnMatchFailure = false;
}
skipIfNecessary(nodes2, nodes, strategy);
if (nodes.hasNext()) {
final MatchingHandler nextHandler = context.getPattern().getHandler(nodes.current());
if (nextHandler.matchSequentially(nodes, nodes2, context)) {
// match was found!
return true;
} else {
// rewind, we was not able to match descendants
nodes.rewind();
if (shouldRewindOnMatchFailure)
nodes2.rewind();
}
} else {
// match was found
return handler.isMatchSequentiallySucceeded(nodes2);
}
}
return false;
}
use of com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy in project intellij-community by JetBrains.
the class MatcherImpl method match.
// Initiates the matching process for given element
// @param element the current search tree element
void match(PsiElement element, final Language language) {
final MatchingStrategy strategy = matchContext.getPattern().getStrategy();
final Language elementLanguage = element.getLanguage();
if (strategy.continueMatching(element) && elementLanguage.isKindOf(language)) {
visitor.matchContext(new ArrayBackedNodeIterator(new PsiElement[] { element }));
return;
}
for (PsiElement el = element.getFirstChild(); el != null; el = el.getNextSibling()) {
match(el, language);
}
if (element instanceof PsiLanguageInjectionHost) {
InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
match(injectedPsi, language);
}
});
}
}
Aggregations