use of com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator in project intellij-community by JetBrains.
the class DeclarationStatementHandler method match.
@Override
public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
if (patternNode instanceof PsiComment) {
return myCommentHandler.match(patternNode, matchedNode, context);
}
if (!super.match(patternNode, matchedNode, context))
return false;
final PsiDeclarationStatement dcl = (PsiDeclarationStatement) patternNode;
if (matchedNode instanceof PsiDeclarationStatement) {
return context.getMatcher().matchSequentially(new SsrFilteringNodeIterator(patternNode.getFirstChild()), new SsrFilteringNodeIterator(matchedNode.getFirstChild()));
}
final PsiElement[] declared = dcl.getDeclaredElements();
// declaration statement could wrap class or dcl
if (declared.length > 0 && !(matchedNode.getParent() instanceof PsiDeclarationStatement)) /* skip twice matching for child*/
{
if (!(matchedNode instanceof PsiField)) {
return context.getMatcher().matchSequentially(new ArrayBackedNodeIterator(declared), new CountingNodeIterator(declared.length, new SsrFilteringNodeIterator(matchedNode)));
}
// special handling for multiple fields in single declaration
final PsiElement sibling = PsiTreeUtil.skipSiblingsBackward(matchedNode, PsiWhiteSpace.class);
if (PsiUtil.isJavaToken(sibling, JavaTokenType.COMMA)) {
return false;
}
final List<PsiElement> matchNodes = new ArrayList<>();
matchNodes.add(matchedNode);
PsiElement node = matchedNode;
node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
while (PsiUtil.isJavaToken(node, JavaTokenType.COMMA)) {
node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
if (node instanceof PsiField) {
matchNodes.add(node);
}
node = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class);
}
boolean result = context.getMatcher().matchSequentially(new ArrayBackedNodeIterator(declared), new ArrayBackedNodeIterator(matchNodes.toArray(new PsiElement[matchNodes.size()])));
if (result && declared[0] instanceof PsiVariable) {
// we may have comments behind to match!
final PsiElement lastChild = dcl.getLastChild();
if (lastChild instanceof PsiComment) {
final PsiElement[] fieldChildren = matchedNode.getChildren();
result = context.getPattern().getHandler(lastChild).match(lastChild, fieldChildren[fieldChildren.length - 1], context);
}
}
return result;
}
return false;
}
use of com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator in project intellij-community by JetBrains.
the class TopLevelMatchingHandler method match.
@Override
public boolean match(final PsiElement patternNode, final PsiElement matchedNode, final MatchContext matchContext) {
final boolean matched = delegate.match(patternNode, matchedNode, matchContext);
if (matched) {
List<PsiElement> matchedNodes = matchContext.getMatchedNodes();
if (matchedNodes == null) {
matchedNodes = new ArrayList<>();
matchContext.setMatchedNodes(matchedNodes);
}
PsiElement elementToAdd = matchedNode;
if (patternNode instanceof PsiComment && StructuralSearchUtil.isDocCommentOwner(matchedNode)) {
// psicomment and psidoccomment are placed inside the psimember next to them so
// simple topdown matching should do additional "dances" to cover this case.
elementToAdd = matchedNode.getFirstChild();
assert elementToAdd instanceof PsiComment;
}
matchedNodes.add(elementToAdd);
}
if ((!matched || matchContext.getOptions().isRecursiveSearch()) && matchContext.getPattern().getStrategy().continueMatching(matchedNode) && matchContext.shouldRecursivelyMatch()) {
matchContext.getMatcher().matchContext(new SsrFilteringNodeIterator(new SiblingNodeIterator(matchedNode.getFirstChild())));
}
return matched;
}
use of com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator in project intellij-community by JetBrains.
the class SSBasedInspection method buildVisitor.
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
final Map<Configuration, MatchContext> compiledOptions = SSBasedInspectionCompiledPatternsCache.getCompiledOptions(myConfigurations, holder.getProject());
if (compiledOptions.isEmpty())
return super.buildVisitor(holder, isOnTheFly);
return new PsiElementVisitor() {
final Matcher matcher = new Matcher(holder.getManager().getProject());
final PairProcessor<MatchResult, Configuration> processor = (matchResult, 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) {
synchronized (LOCK) {
if (LexicalNodesFilter.getInstance().accepts(element))
return;
final SsrFilteringNodeIterator matchedNodes = new SsrFilteringNodeIterator(element);
for (Map.Entry<Configuration, MatchContext> entry : compiledOptions.entrySet()) {
Configuration configuration = entry.getKey();
MatchContext context = entry.getValue();
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();
}
}
}
}
};
}
use of com.intellij.structuralsearch.impl.matcher.iterators.SsrFilteringNodeIterator in project intellij-community by JetBrains.
the class MatcherImpl method findMatches.
/**
* Finds the matches of given pattern starting from given tree element.
* @throws MalformedPatternException
* @throws UnsupportedPatternException
*/
protected void findMatches(MatchResultSink sink, final MatchOptions options) throws MalformedPatternException, UnsupportedPatternException {
CompiledPattern compiledPattern = prepareMatching(sink, options);
if (compiledPattern == null) {
return;
}
matchContext.getSink().setMatchingProcess(scheduler);
scheduler.init();
progress = matchContext.getSink().getProgressIndicator();
if (isTesting) {
// testing mode;
final PsiElement[] elements = ((LocalSearchScope) options.getScope()).getScope();
PsiElement parent = elements[0].getParent();
if (elements.length > 0 && matchContext.getPattern().getStrategy().continueMatching(parent != null ? parent : elements[0])) {
visitor.matchContext(new SsrFilteringNodeIterator(new ArrayBackedNodeIterator(elements)));
} else {
final LanguageFileType fileType = (LanguageFileType) matchContext.getOptions().getFileType();
final Language language = fileType.getLanguage();
for (PsiElement element : elements) {
match(element, language);
}
}
matchContext.getSink().matchingFinished();
return;
}
if (!findMatches(options, compiledPattern)) {
return;
}
if (scheduler.getTaskQueueEndAction() == null) {
scheduler.setTaskQueueEndAction(() -> matchContext.getSink().matchingFinished());
}
scheduler.executeNext();
}
Aggregations