void (RegExpGroup group) { if (RegExpGroupImpl.isPcreConditionalGroup(group.getNode())) { if (RegExpGroupImpl.isPcreDefine(group.getNode())) { RegExpConditional conditional = ObjectUtils.tryCast(group.getParent(), RegExpConditional.class); if (conditional != null) { RegExpBranch[] branches = PsiTreeUtil.getChildrenOfType(conditional, RegExpBranch.class); if (branches != null && branches.length > 1) { myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.define.subpattern.contains.more.than.one.branch")).create(); } } } return; } final RegExpPattern pattern = group.getPattern(); final RegExpBranch[] branches = pattern.getBranches(); if (isEmpty(branches) && group.getNode().getLastChildNode().getElementType() == RegExpTT.GROUP_END) { // catches "()" as well as "(|)" myHolder.newAnnotation(HighlightSeverity.WARNING, RegExpBundle.message("error.empty.group")).create(); } else if (branches.length == 1) { final RegExpAtom[] atoms = branches[0].getAtoms(); if (atoms.length == 1 && atoms[0] instanceof RegExpGroup) { final RegExpGroup.Type type = group.getType(); if (type == RegExpGroup.Type.CAPTURING_GROUP || type == RegExpGroup.Type.ATOMIC || type == RegExpGroup.Type.NON_CAPTURING) { final RegExpGroup innerGroup = (RegExpGroup)atoms[0]; if (group.isCapturing() == innerGroup.isCapturing()) { myHolder.newAnnotation(HighlightSeverity.WARNING, RegExpBundle.message("error.redundant.group.nesting")).create(); } } } } if (group.isAnyNamedGroup()) { if (!myLanguageHosts.supportsNamedGroupSyntax(group)) { myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.this.named.group.syntax.is.not.supported.in.this.regex.dialect")).create(); } } if (group.getType() == RegExpGroup.Type.ATOMIC && !myLanguageHosts.supportsPossessiveQuantifiers(group)) { myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.atomic.groups.are.not.supported.in.this.regex.dialect")) .create(); } final String name = group.getName(); if (name != null && !myLanguageHosts.isValidGroupName(name, group)) { final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME); if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.invalid.group.name")).range(node) .create(); } final AnnotationSession session = myHolder.getCurrentAnnotationSession(); final Map<String, RegExpGroup> namedGroups = NAMED_GROUP_MAP.get(session, new HashMap<>()); if (namedGroups.isEmpty()) session.putUserData(NAMED_GROUP_MAP, namedGroups); if (namedGroups.put(name, group) != null && !myLanguageHosts.isDuplicateGroupNamesAllowed(group)) { final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME); if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.group.with.name.0.already.defined", name)).range(node).create(); } final RegExpGroup.Type groupType = group.getType(); if (groupType == RegExpGroup.Type.POSITIVE_LOOKBEHIND || groupType == RegExpGroup.Type.NEGATIVE_LOOKBEHIND) { final RegExpLanguageHost.Lookbehind support = myLanguageHosts.supportsLookbehind(group); if (support == RegExpLanguageHost.Lookbehind.NOT_SUPPORTED) { myHolder.newAnnotation(HighlightSeverity.ERROR, RegExpBundle.message("error.look.behind.groups.are.not.supported.in.this.regex.dialect")).create(); } else { group.accept(new LookbehindVisitor(support, myHolder)); } } }