List<PsiReference> (TextRange range, int index) { String orderPart = range.substring(orderValue); // reference range and attribute text range are not equal range = new TextRange(range.getStartOffset() + 1, range.getEndOffset() + 1); List<String> subParts = splitOrderPart(orderPart); if (subParts.isEmpty()) { // last symbol is ',' return Collections.emptyList(); } // second one, after keyword sub-part String idSubPart = null; if (subParts.size() == 2) { idSubPart = subParts.get(1); } else if (isBeforeOrAfterKeyword(StringUtil.trimLeading(orderPart), false)) { // This order part is, for instance, 'after ' or 'before:'. In such cases IDs reference should be provided. idSubPart = ""; } if (subParts.size() > 2 || (idSubPart != null && !isBeforeOrAfterKeyword(subParts.get(0)))) { // Order value can't contain more than 3 subparts. If there are two subparts, first one must be 'before' or 'after'. return Collections.singletonList(new InvalidOrderPartPsiReference(getElement(), range, orderPart)); } List<TextRange> wordIndices = getWordIndicesInOrderPart(orderPart); if (wordIndices.isEmpty()) { LOG.error("Unexpected empty word indices list for 'order' part: " + orderPart); return Collections.singletonList(new InvalidOrderPartPsiReference(getElement(), range, orderPart)); } if (idSubPart != null && idSubPart.isEmpty()) { // right after the before/after keyword wordIndices.add(new TextRange(orderPart.length(), orderPart.length())); } if (idSubPart == null) { return Collections.emptyList(); } assert wordIndices.size() == 2 : wordIndices.toString(); TextRange idSubPartRange = wordIndices.get(1).shiftRight(range.getStartOffset()); return Collections.singletonList(new OrderReferencedIdPsiReference(getElement(), idSubPartRange, idSubPart, extension)); }