use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator 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.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.
the class CompiledPattern method setNodes.
public void setNodes(List<PsiElement> elements) {
this.nodes = new ArrayBackedNodeIterator(PsiUtilCore.toPsiElementArray(elements));
this.nodeCount = elements.size();
}
use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator in project intellij-community by JetBrains.
the class JavaMatchingVisitor method compareClasses.
private boolean compareClasses(final PsiClass clazz, final PsiClass clazz2) {
final PsiClass saveClazz = this.myClazz;
final MatchContext.MatchedElementsListener oldListener = myMatchingVisitor.getMatchContext().getMatchedElementsListener();
this.myClazz = clazz2;
final CompiledPattern pattern = myMatchingVisitor.getMatchContext().getPattern();
assert pattern instanceof JavaCompiledPattern;
final JavaCompiledPattern javaPattern = (JavaCompiledPattern) pattern;
MatchContext.MatchedElementsListener listener = new MatchContext.MatchedElementsListener() {
private Set<PsiElement> myMatchedElements;
@Override
public void matchedElements(Collection<PsiElement> matchedElements) {
if (matchedElements == null)
return;
if (myMatchedElements == null) {
myMatchedElements = new HashSet<>(matchedElements);
} else {
myMatchedElements.addAll(matchedElements);
}
}
@Override
public void commitUnmatched() {
final List<PsiMember> members = PsiTreeUtil.getChildrenOfTypeAsList(clazz2, PsiMember.class);
final List<PsiMember> unmatchedElements = ContainerUtil.filter(members, a -> myMatchedElements == null || !myMatchedElements.contains(a));
MatchingHandler unmatchedSubstitutionHandler = null;
for (PsiElement element = clazz.getFirstChild(); element != null; element = element.getNextSibling()) {
if (element instanceof PsiTypeElement && element.getNextSibling() instanceof PsiErrorElement) {
unmatchedSubstitutionHandler = pattern.getHandler(element);
break;
}
}
if (unmatchedSubstitutionHandler instanceof SubstitutionHandler) {
final SubstitutionHandler handler = (SubstitutionHandler) unmatchedSubstitutionHandler;
for (PsiMember element : unmatchedElements) {
handler.handle(element, myMatchingVisitor.getMatchContext());
}
} else {
clazz2.putUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY, unmatchedElements);
}
}
};
myMatchingVisitor.getMatchContext().setMatchedElementsListener(listener);
boolean result = false;
try {
final boolean templateIsInterface = clazz.isInterface();
if (templateIsInterface != clazz2.isInterface())
return false;
if (templateIsInterface && clazz.isAnnotationType() && !clazz2.isAnnotationType())
return false;
if (clazz.isEnum() && !clazz2.isEnum())
return false;
if (!matchInAnyOrder(clazz.getExtendsList(), clazz2.getExtendsList())) {
return false;
}
// check if implements is in extended classes implements
final PsiReferenceList implementsList = clazz.getImplementsList();
if (implementsList != null) {
if (!matchInAnyOrder(implementsList, clazz2.getImplementsList())) {
final PsiReferenceList anotherExtendsList = clazz2.getExtendsList();
final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
boolean accepted = false;
if (referenceElements.length > 0 && anotherExtendsList != null) {
final HierarchyNodeIterator iterator = new HierarchyNodeIterator(clazz2, true, true, false);
accepted = myMatchingVisitor.matchInAnyOrder(new ArrayBackedNodeIterator(referenceElements), iterator);
}
if (!accepted)
return false;
}
}
final PsiField[] fields = clazz.getFields();
if (fields.length > 0) {
final PsiField[] fields2 = javaPattern.isRequestsSuperFields() ? clazz2.getAllFields() : clazz2.getFields();
if (!myMatchingVisitor.matchInAnyOrder(fields, fields2)) {
return false;
}
}
final PsiMethod[] methods = clazz.getMethods();
if (methods.length > 0) {
final PsiMethod[] methods2 = javaPattern.isRequestsSuperMethods() ? clazz2.getAllMethods() : clazz2.getMethods();
if (!myMatchingVisitor.matchInAnyOrder(methods, methods2)) {
return false;
}
}
final PsiClass[] nestedClasses = clazz.getInnerClasses();
if (nestedClasses.length > 0) {
final PsiClass[] nestedClasses2 = javaPattern.isRequestsSuperInners() ? clazz2.getAllInnerClasses() : clazz2.getInnerClasses();
if (!myMatchingVisitor.matchInAnyOrder(nestedClasses, nestedClasses2)) {
return false;
}
}
final PsiClassInitializer[] initializers = clazz.getInitializers();
if (initializers.length > 0) {
final PsiClassInitializer[] initializers2 = clazz2.getInitializers();
if (!myMatchingVisitor.matchInAnyOrder(initializers, initializers2)) {
return false;
}
}
result = true;
return true;
} finally {
if (result)
listener.commitUnmatched();
this.myClazz = saveClazz;
myMatchingVisitor.getMatchContext().setMatchedElementsListener(oldListener);
}
}
use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator 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);
}
});
}
}
use of com.intellij.dupLocator.iterators.ArrayBackedNodeIterator 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