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; }
@NotNull private static JBIterable<PsiElement> getSiblings(PsiElement element, boolean fwd) { SyntaxTraverser.ApiEx<PsiElement> api = fwd ? SyntaxTraverser.psiApi() : SyntaxTraverser.psiApiReversed(); JBIterable<PsiElement> flatSiblings = JBIterable.generate(element, api::next).skip(1); return SyntaxTraverser.syntaxTraverser(api) .withRoots(flatSiblings) .expandAndSkip(e -> api.typeOf(e) == GeneratedParserUtilBase.DUMMY_BLOCK) .traverse(); }