void (PsiElement @NotNull [] 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(@NotNull PsiElement element) { super.visitElement(element); if (DuplocatorUtil.isIgnoredNode(element)) { return; } final CompiledPattern pattern = globalVisitor.getContext().getPattern(); final MatchingHandler handler = pattern.getHandler(element); if (!(handler instanceof SubstitutionHandler) && !(handler instanceof TopLevelMatchingHandler) && !(handler instanceof LightTopLevelMatchingHandler)) { pattern.setHandler(element, new SkippingHandler(handler)); } // todo: simplify logic /* 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) { final 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(); final PsiFile file = start.getContainingFile(); if (file != null) { final 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); } }); }