@SuppressWarnings("AssignmentToForLoopParameter") @NotNull private static TextRange processSmartTabs(@NotNull Helper helper,@NotNull TextRange range,int tabWidth){
  CharSequence prevLineIndent=helper.getPrevLineIndent();
  if (prevLineIndent == null) {
    return processTabs(helper,range,tabWidth);
  }
  CharSequence currentLineIndent=helper.getCurrentLineIndent();
  int lineStart=0;
  int start=Math.max(0,range.getStartOffset() - helper.getCurrentLineStartOffset());
  int end=Math.min(currentLineIndent.length(),range.getEndOffset() - helper.getCurrentLineStartOffset());
  int indentOffset=0;
  int tabsReplaced=0;
  for (int i=lineStart; i < end && indentOffset < prevLineIndent.length(); i++, indentOffset++) {
    char c=currentLineIndent.charAt(i);
    if (prevLineIndent.charAt(indentOffset) == ' ') {
      if (c == ' ') {
        continue;
      }
 else {
        break;
      }
    }
    if (c == '\t') {
      continue;
    }
    if (end - i < tabWidth) {
      break;
    }
    boolean canReplace=true;
    for (int j=i + 1, max=Math.min(end,i + tabWidth); j < max; j++) {
      if (currentLineIndent.charAt(j) != ' ') {
        canReplace=false;
        break;
      }
    }
    if (!canReplace) {
      break;
    }
    if (i < start) {
      i+=tabWidth - 1;
      continue;
    }
    helper.replace(i,i + tabWidth,"\t");
    tabsReplaced++;
    end-=tabWidth - 1;
  }
  return tabsReplaced > 0 ? TextRange.create(range.getStartOffset(),range.getEndOffset() - tabsReplaced * (tabWidth - 1)) : range;
}

@ SuppressWarnings ( "AssignmentToForLoopParameter" ) @ NotNull private static TextRange processSmartTabs ( @ NotNull Helper helper , @ NotNull TextRange range , int tabWidth ) { CharSequence prevLineIndent = helper . getPrevLineIndent ( ) ; if ( prevLineIndent == null ) { return processTabs ( helper , range , tabWidth ) ; } CharSequence currentLineIndent = helper . getCurrentLineIndent ( ) ; int lineStart = 0 ; int start = Math . max ( 0 , range . getStartOffset ( ) - helper . getCurrentLineStartOffset ( ) ) ; int end = Math . min ( currentLineIndent . length ( ) , range . getEndOffset ( ) - helper . getCurrentLineStartOffset ( ) ) ; int indentOffset = 0 ; int tabsReplaced = 0 ; for ( int i = lineStart ; i < end && indentOffset < prevLineIndent . length ( ) ; i ++ , indentOffset ++ ) { char c = currentLineIndent . charAt ( i ) ; if ( prevLineIndent . charAt ( indentOffset ) == ' ' ) { if ( c == ' ' ) { continue ; } else { break ; } } if ( c == '\t' ) { continue ; } if ( end - i < tabWidth ) { break ; } boolean canReplace = true ; for ( int j = i + 1 , max = Math . min ( end , i + tabWidth ) ; j < max ; j ++ ) { if ( currentLineIndent . charAt ( j ) != ' ' ) { canReplace = false ; break ; } } if ( ! canReplace ) { break ; } if ( i < start ) { i += tabWidth - 1 ; continue ; } helper . replace ( i , i + tabWidth , "\t" ) ; tabsReplaced ++ ; end -= tabWidth - 1 ; } return tabsReplaced > 0 ? TextRange . create ( range . getStartOffset ( ) , range . getEndOffset ( ) - tabsReplaced * ( tabWidth - 1 ) ) : range ; }
converts tabulations to white spaces at the target line ' s indent space .
