public static List<PsiLambdaExpression> collectLambdas( @NotNull SourcePosition position, final boolean onlyOnTheLine) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFile file = position.getFile(); final int line = position.getLine(); final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null || line >= document.getLineCount()) { return Collections.emptyList(); } PsiElement element = position.getElementAt(); final TextRange lineRange = DocumentUtil.getLineTextRange(document, line); do { PsiElement parent = element.getParent(); if (parent == null || (parent.getTextOffset() < lineRange.getStartOffset())) { break; } element = parent; } while (true); final List<PsiLambdaExpression> lambdas = new ArrayList<PsiLambdaExpression>(3); final PsiElementVisitor lambdaCollector = new JavaRecursiveElementVisitor() { @Override public void visitLambdaExpression(PsiLambdaExpression expression) { super.visitLambdaExpression(expression); if (!onlyOnTheLine || getFirstElementOnTheLine(expression, document, line) != null) { lambdas.add(expression); } } }; element.accept(lambdaCollector); // add initial lambda if we're inside already PsiElement method = getContainingMethod(element); if (method instanceof PsiLambdaExpression) { lambdas.add((PsiLambdaExpression) method); } for (PsiElement sibling = getNextElement(element); sibling != null; sibling = getNextElement(sibling)) { if (!intersects(lineRange, sibling)) { break; } sibling.accept(lambdaCollector); } return lambdas; }
private static TextRange adjustRange(final PsiElement element, final TextRange originalRange) { final Ref<TextRange> rangeRef = new Ref<TextRange>(originalRange); element.accept( new JavaRecursiveElementVisitor() { @Override public void visitExpressionStatement(final PsiExpressionStatement statement) { final TextRange stRange = statement.getTextRange(); if (originalRange.intersects(stRange)) { final TextRange currentRange = rangeRef.get(); final int start = Math.min(currentRange.getStartOffset(), stRange.getStartOffset()); final int end = Math.max(currentRange.getEndOffset(), stRange.getEndOffset()); rangeRef.set(new TextRange(start, end)); } } }); return rangeRef.get(); }
@Override public String getUnescapedText(@NotNull final PsiElement injectedNode) { final StringBuilder text = new StringBuilder(injectedNode.getTextLength()); // gather text from (patched) leaves injectedNode.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { String unescaped = element.getCopyableUserData(UNESCAPED_TEXT); if (unescaped != null) { text.append(unescaped); return; } if (element.getFirstChild() == null) { text.append(element.getText()); return; } super.visitElement(element); } }); return text.toString(); }
private static Pair<Set<String>, Set<TextWithImports>> findReferencedVars( Set<String> visibleVars, SourcePosition position) { final int line = position.getLine(); if (line < 0) { return Pair.create(Collections.<String>emptySet(), Collections.<TextWithImports>emptySet()); } final PsiFile positionFile = position.getFile(); if (!positionFile.getLanguage().isKindOf(JavaLanguage.INSTANCE)) { return Pair.create(visibleVars, Collections.<TextWithImports>emptySet()); } final VirtualFile vFile = positionFile.getVirtualFile(); final Document doc = vFile != null ? FileDocumentManager.getInstance().getDocument(vFile) : null; if (doc == null || doc.getLineCount() == 0 || line > (doc.getLineCount() - 1)) { return Pair.create(Collections.<String>emptySet(), Collections.<TextWithImports>emptySet()); } final TextRange limit = calculateLimitRange(positionFile, doc, line); int startLine = Math.max(limit.getStartOffset(), line - 1); startLine = Math.min(startLine, limit.getEndOffset()); while (startLine > limit.getStartOffset() && shouldSkipLine(positionFile, doc, startLine)) { startLine--; } final int startOffset = doc.getLineStartOffset(startLine); int endLine = Math.min(line + 2, limit.getEndOffset()); while (endLine < limit.getEndOffset() && shouldSkipLine(positionFile, doc, endLine)) { endLine++; } final int endOffset = doc.getLineEndOffset(endLine); final TextRange lineRange = new TextRange(startOffset, endOffset); if (!lineRange.isEmpty()) { final int offset = CharArrayUtil.shiftForward(doc.getCharsSequence(), doc.getLineStartOffset(line), " \t"); PsiElement element = positionFile.findElementAt(offset); if (element != null) { PsiMethod method = PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class); if (method != null) { element = method; } else { PsiField field = PsiTreeUtil.getNonStrictParentOfType(element, PsiField.class); if (field != null) { element = field; } else { final PsiClassInitializer initializer = PsiTreeUtil.getNonStrictParentOfType(element, PsiClassInitializer.class); if (initializer != null) { element = initializer; } } } //noinspection unchecked if (element instanceof PsiCompiledElement) { return Pair.create(visibleVars, Collections.<TextWithImports>emptySet()); } else { VariablesCollector collector = new VariablesCollector(visibleVars, adjustRange(element, lineRange)); element.accept(collector); return Pair.create(collector.getVars(), collector.getExpressions()); } } } return Pair.create(Collections.<String>emptySet(), Collections.<TextWithImports>emptySet()); }