/**
   * check whether statement is return (the statement which provides return value) statement of
   * method or closure.
   *
   * @param st
   * @return
   */
  public static boolean isCertainlyReturnStatement(GrStatement st) {
    final PsiElement parent = st.getParent();
    if (parent instanceof GrOpenBlock) {
      if (st != ArrayUtil.getLastElement(((GrOpenBlock) parent).getStatements())) return false;

      PsiElement pparent = parent.getParent();
      if (pparent instanceof GrMethod) {
        return true;
      }

      if (pparent instanceof GrBlockStatement
          || pparent instanceof GrCatchClause
          || pparent instanceof GrLabeledStatement) {
        pparent = pparent.getParent();
      }
      if (pparent instanceof GrIfStatement
          || pparent instanceof GrControlStatement
          || pparent instanceof GrTryCatchStatement) {
        return isCertainlyReturnStatement((GrStatement) pparent);
      }
    } else if (parent instanceof GrClosableBlock) {
      return st == ArrayUtil.getLastElement(((GrClosableBlock) parent).getStatements());
    } else if (parent instanceof GroovyFileBase) {
      return st == ArrayUtil.getLastElement(((GroovyFileBase) parent).getStatements());
    } else if (parent instanceof GrForStatement
        || parent instanceof GrIfStatement && st != ((GrIfStatement) parent).getCondition()
        || parent instanceof GrSynchronizedStatement
            && st != ((GrSynchronizedStatement) parent).getMonitor()
        || parent instanceof GrWhileStatement && st != ((GrWhileStatement) parent).getCondition()
        || parent instanceof GrConditionalExpression
            && st != ((GrConditionalExpression) parent).getCondition()
        || parent instanceof GrElvisExpression) {
      return isCertainlyReturnStatement((GrStatement) parent);
    } else if (parent instanceof GrCaseSection) {
      final GrStatement[] statements = ((GrCaseSection) parent).getStatements();
      final GrStatement last = ArrayUtil.getLastElement(statements);
      final GrSwitchStatement switchStatement = (GrSwitchStatement) parent.getParent();

      if (last instanceof GrBreakStatement
          && statements.length > 1
          && statements[statements.length - 2] == st) {
        return isCertainlyReturnStatement(switchStatement);
      } else if (st == last) {
        if (st instanceof GrBreakStatement
            || isLastStatementInCaseSection((GrCaseSection) parent, switchStatement)) {
          return isCertainlyReturnStatement(switchStatement);
        }
      }
    }
    return false;
  }
 @Override
 public void doApply(
     @NotNull Editor editor,
     @NotNull PySmartEnterProcessor processor,
     @NotNull PyWithStatement withStatement)
     throws IncorrectOperationException {
   final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
   final PsiElement withToken =
       PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
   final Document document = editor.getDocument();
   if (colonToken == null && withToken != null) {
     int insertAt = withToken.getTextRange().getEndOffset();
     String textToInsert = ":";
     final PyWithItem lastItem = ArrayUtil.getLastElement(withStatement.getWithItems());
     if (lastItem == null || lastItem.getExpression() == null) {
       textToInsert = " :";
       processor.registerUnresolvedError(insertAt + 1);
     } else {
       final PyExpression expression = lastItem.getExpression();
       insertAt = expression.getTextRange().getEndOffset();
       final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
       if (asToken != null) {
         insertAt = asToken.getTextRange().getEndOffset();
         final PyExpression target = lastItem.getTarget();
         if (target != null) {
           insertAt = target.getTextRange().getEndOffset();
         } else {
           textToInsert = " :";
           processor.registerUnresolvedError(insertAt + 1);
         }
       }
     }
     document.insertString(insertAt, textToInsert);
   }
 }
 private VirtualFile createNlsByPath(@NotNull VirtualFile nlsRoot, @NotNull String[] chunks)
     throws IOException {
   VirtualFile currentFolder = nlsRoot;
   for (int i = 0; i < chunks.length - 1; i++) {
     String chunk = chunks[i];
     VirtualFile nextFolder = currentFolder.findChild(chunk);
     if (nextFolder == null) {
       nextFolder = currentFolder.createChildDirectory(this, chunk);
     }
     currentFolder = nextFolder;
   }
   //noinspection ConstantConditions
   return currentFolder.createChildData(this, ArrayUtil.getLastElement(chunks));
 }
 @Override
 public XmlTag addSubTag(XmlTag subTag, boolean first) {
   XmlTagChild[] children = getSubTags();
   if (children.length == 0) {
     children = getValue().getChildren();
   }
   if (children.length == 0) {
     return (XmlTag) add(subTag);
   } else if (first) {
     return (XmlTag) addBefore(subTag, children[0]);
   } else {
     return (XmlTag) addAfter(subTag, ArrayUtil.getLastElement(children));
   }
 }