private int getPrevOrNextParameterOffset(boolean isNext) { if (!(myHandler instanceof ParameterInfoHandlerWithTabActionSupport)) return -1; ParameterInfoHandlerWithTabActionSupport handler = (ParameterInfoHandlerWithTabActionSupport) myHandler; boolean noDelimiter = handler.getActualParameterDelimiterType() == TokenType.WHITE_SPACE; int caretOffset = myEditor.getCaretModel().getOffset(); int offset = noDelimiter ? caretOffset : CharArrayUtil.shiftBackward( myEditor.getDocument().getCharsSequence(), caretOffset - 1, " \t") + 1; int lbraceOffset = myLbraceMarker.getStartOffset(); PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument()); PsiElement argList = lbraceOffset < offset ? findArgumentList(file, offset, lbraceOffset) : null; if (argList == null) return -1; @SuppressWarnings("unchecked") PsiElement[] parameters = handler.getActualParameters(argList); int currentParameterIndex = noDelimiter ? JBIterable.of(parameters).indexOf((o) -> o.getTextRange().containsOffset(offset)) : ParameterInfoUtils.getCurrentParameterIndex( argList.getNode(), offset, handler.getActualParameterDelimiterType()); int prevOrNextParameterIndex = isNext && currentParameterIndex < parameters.length - 1 ? currentParameterIndex + 1 : !isNext && currentParameterIndex > 0 ? currentParameterIndex - 1 : -1; return prevOrNextParameterIndex != -1 ? parameters[prevOrNextParameterIndex].getTextRange().getStartOffset() : -1; }
@Nullable public static <E extends PsiElement> E findArgumentList( PsiFile file, int offset, int lbraceOffset, @NotNull ParameterInfoHandlerWithTabActionSupport findArgumentListHelper) { if (file == null) return null; CharSequence chars = file.getViewProvider().getContents(); if (offset >= chars.length()) offset = chars.length() - 1; int offset1 = CharArrayUtil.shiftBackward(chars, offset, " \t\n\r"); if (offset1 < 0) return null; boolean acceptRparenth = true; boolean acceptLparenth = false; if (offset1 != offset) { offset = offset1; acceptRparenth = false; acceptLparenth = true; } PsiElement element = file.findElementAt(offset); if (element == null) return null; PsiElement parent = element.getParent(); while (true) { if (findArgumentListHelper.getArgumentListClass().isInstance(parent)) { TextRange range = parent.getTextRange(); if (!acceptRparenth) { if (offset == range.getEndOffset() - 1) { PsiElement[] children = parent.getChildren(); if (children.length == 0) return null; PsiElement last = children[children.length - 1]; if (last.getNode().getElementType() == findArgumentListHelper.getActualParametersRBraceType()) { parent = parent.getParent(); continue; } } } if (!acceptLparenth) { if (offset == range.getStartOffset()) { parent = parent.getParent(); continue; } } if (lbraceOffset >= 0 && range.getStartOffset() != lbraceOffset) { parent = parent.getParent(); continue; } break; } if (parent instanceof PsiFile || parent == null) return null; final Set<? extends Class> set = findArgumentListHelper.getArgListStopSearchClasses(); for (Class aClass : set) { if (aClass.isInstance(parent)) return null; } parent = parent.getParent(); } PsiElement listParent = parent.getParent(); for (Class c : (Set<Class>) findArgumentListHelper.getArgumentListAllowedParentClasses()) { if (c.isInstance(listParent)) return (E) parent; } return null; }