Lines 1-5
Link Here
|
1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2000, 2009 IBM Corporation and others. |
2 |
* Copyright (c) 2000, 2011 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
Lines 22-27
Link Here
|
22 |
|
22 |
|
23 |
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; |
23 |
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; |
24 |
|
24 |
|
|
|
25 |
import org.eclipse.jdt.internal.ui.JavaPlugin; |
25 |
|
26 |
|
26 |
/** |
27 |
/** |
27 |
* Uses the {@link org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner} to |
28 |
* Uses the {@link org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner} to |
Lines 50-56
Link Here
|
50 |
final boolean prefTernaryDeepAlign; |
51 |
final boolean prefTernaryDeepAlign; |
51 |
final int prefTernaryIndent; |
52 |
final int prefTernaryIndent; |
52 |
final int prefCaseIndent; |
53 |
final int prefCaseIndent; |
53 |
final int prefAssignmentIndent; |
|
|
54 |
final int prefCaseBlockIndent; |
54 |
final int prefCaseBlockIndent; |
55 |
final int prefSimpleIndent; |
55 |
final int prefSimpleIndent; |
56 |
final int prefBracketIndent; |
56 |
final int prefBracketIndent; |
Lines 110-116
Link Here
|
110 |
prefTernaryDeepAlign= false; |
110 |
prefTernaryDeepAlign= false; |
111 |
prefTernaryIndent= prefContinuationIndent; |
111 |
prefTernaryIndent= prefContinuationIndent; |
112 |
prefCaseIndent= 0; |
112 |
prefCaseIndent= 0; |
113 |
prefAssignmentIndent= prefBlockIndent; |
|
|
114 |
prefCaseBlockIndent= prefBlockIndent; |
113 |
prefCaseBlockIndent= prefBlockIndent; |
115 |
prefIndentBracesForBlocks= false; |
114 |
prefIndentBracesForBlocks= false; |
116 |
prefSimpleIndent= (prefIndentBracesForBlocks && prefBlockIndent == 0) ? 1 : prefBlockIndent; |
115 |
prefSimpleIndent= (prefIndentBracesForBlocks && prefBlockIndent == 0) ? 1 : prefBlockIndent; |
Lines 140-146
Link Here
|
140 |
prefTernaryDeepAlign= prefTernaryDeepAlign(); |
139 |
prefTernaryDeepAlign= prefTernaryDeepAlign(); |
141 |
prefTernaryIndent= prefTernaryIndent(); |
140 |
prefTernaryIndent= prefTernaryIndent(); |
142 |
prefCaseIndent= prefCaseIndent(); |
141 |
prefCaseIndent= prefCaseIndent(); |
143 |
prefAssignmentIndent= prefAssignmentIndent(); |
|
|
144 |
prefCaseBlockIndent= prefCaseBlockIndent(); |
142 |
prefCaseBlockIndent= prefCaseBlockIndent(); |
145 |
prefIndentBracesForBlocks= prefIndentBracesForBlocks(); |
143 |
prefIndentBracesForBlocks= prefIndentBracesForBlocks(); |
146 |
prefSimpleIndent= prefSimpleIndent(); |
144 |
prefSimpleIndent= prefSimpleIndent(); |
Lines 231-240
Link Here
|
231 |
return 0; |
229 |
return 0; |
232 |
} |
230 |
} |
233 |
|
231 |
|
234 |
private int prefAssignmentIndent() { |
|
|
235 |
return prefBlockIndent(); |
236 |
} |
237 |
|
238 |
private int prefCaseBlockIndent() { |
232 |
private int prefCaseBlockIndent() { |
239 |
if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES))) |
233 |
if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES))) |
240 |
return prefBlockIndent(); |
234 |
return prefBlockIndent(); |
Lines 750-755
Link Here
|
750 |
boolean matchBrace= false; |
744 |
boolean matchBrace= false; |
751 |
boolean matchParen= false; |
745 |
boolean matchParen= false; |
752 |
boolean matchCase= false; |
746 |
boolean matchCase= false; |
|
|
747 |
boolean throwsClause= false; |
753 |
|
748 |
|
754 |
// account for un-indentation characters already typed in, but after position |
749 |
// account for un-indentation characters already typed in, but after position |
755 |
// if they are on a line by themselves, the indentation gets adjusted |
750 |
// if they are on a line by themselves, the indentation gets adjusted |
Lines 777-783
Link Here
|
777 |
case Symbols.TokenLBRACE: // for opening-brace-on-new-line style |
772 |
case Symbols.TokenLBRACE: // for opening-brace-on-new-line style |
778 |
if (bracelessBlockStart && !fPrefs.prefIndentBracesForBlocks) |
773 |
if (bracelessBlockStart && !fPrefs.prefIndentBracesForBlocks) |
779 |
unindent= true; |
774 |
unindent= true; |
780 |
else if ((prevToken == Symbols.TokenCOLON || prevToken == Symbols.TokenEQUAL || prevToken == Symbols.TokenRBRACKET) && !fPrefs.prefIndentBracesForArrays) |
775 |
else if ((prevToken == Symbols.TokenCOLON || prevToken == Symbols.TokenEQUAL) && !fPrefs.prefIndentBracesForArrays) |
781 |
unindent= true; |
776 |
unindent= true; |
782 |
else if (!bracelessBlockStart && fPrefs.prefIndentBracesForMethods) |
777 |
else if (!bracelessBlockStart && fPrefs.prefIndentBracesForMethods) |
783 |
indent= true; |
778 |
indent= true; |
Lines 790-795
Link Here
|
790 |
if (isFirstTokenOnLine) |
785 |
if (isFirstTokenOnLine) |
791 |
matchParen= true; |
786 |
matchParen= true; |
792 |
break; |
787 |
break; |
|
|
788 |
case Symbols.TokenTHROWS: |
789 |
throwsClause= true; |
790 |
break; |
791 |
case Symbols.TokenPLUS: |
792 |
int position= handleStringContinuation(offset); |
793 |
if (position != JavaHeuristicScanner.NOT_FOUND) { |
794 |
fAlign= JavaHeuristicScanner.NOT_FOUND; |
795 |
fIndent= fPrefs.prefContinuationIndent; |
796 |
return position; |
797 |
} |
798 |
break; |
793 |
} |
799 |
} |
794 |
} catch (BadLocationException e) { |
800 |
} catch (BadLocationException e) { |
795 |
} |
801 |
} |
Lines 798-804
Link Here
|
798 |
danglingElse= false; |
804 |
danglingElse= false; |
799 |
} |
805 |
} |
800 |
|
806 |
|
801 |
int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase); |
807 |
int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, throwsClause); |
802 |
if (unindent) |
808 |
if (unindent) |
803 |
fIndent--; |
809 |
fIndent--; |
804 |
if (indent) |
810 |
if (indent) |
Lines 807-833
Link Here
|
807 |
} |
813 |
} |
808 |
|
814 |
|
809 |
/** |
815 |
/** |
810 |
* Returns the reference position regarding to indentation for <code>position</code>, |
816 |
* Specifically handles the case of extra indentation for second line of string continuation. |
811 |
* or <code>NOT_FOUND</code>.<code>fIndent</code> will contain the |
817 |
* |
812 |
* relative indentation (in indentation units, not characters) after the |
818 |
* @param offset the offset for which the reference is computed |
813 |
* call. If there is a special alignment (e.g. for a method declaration |
819 |
* @return the reference statement relative to which <code>offset</code> should be indented, or |
814 |
* where parameters should be aligned), <code>fAlign</code> will contain |
820 |
* {@link JavaHeuristicScanner#NOT_FOUND} |
815 |
* the absolute position of the alignment reference in <code>fDocument</code>, |
821 |
* @since 3.7 |
816 |
* otherwise <code>fAlign</code> is set to <code>JavaHeuristicScanner.NOT_FOUND</code>. |
822 |
*/ |
817 |
* |
823 |
private int handleStringContinuation(int offset) { |
|
|
824 |
int prevNonWSCharPosition= fScanner.findNonWhitespaceBackwardInAnyPartition(offset - 1, JavaHeuristicScanner.UNBOUND); |
825 |
if (prevNonWSCharPosition != JavaHeuristicScanner.NOT_FOUND) { |
826 |
try { |
827 |
char c= fDocument.getChar(prevNonWSCharPosition); |
828 |
if (c == '"' || c == '+') { |
829 |
int initialLine= fDocument.getLineOfOffset(offset); |
830 |
nextToken(offset); |
831 |
while (fToken == Symbols.TokenPLUS) { |
832 |
if ((initialLine - fLine) > 1) |
833 |
return JavaHeuristicScanner.NOT_FOUND; |
834 |
nextToken(); |
835 |
} |
836 |
int lineDiff= initialLine - fLine; |
837 |
if (lineDiff > 0) { |
838 |
int bound= fDocument.getLineOffset(fLine) + fDocument.getLineLength(fLine) - 1; |
839 |
int nextNonWSCharPosition= fScanner.findNonWhitespaceForwardInAnyPartition(fPosition + 1, bound); |
840 |
if (lineDiff < 3 && fPreviousPos != offset && nextNonWSCharPosition != JavaHeuristicScanner.NOT_FOUND && fDocument.getChar(nextNonWSCharPosition) != '"') |
841 |
return fPreviousPos; |
842 |
else |
843 |
return fPosition; |
844 |
} |
845 |
} |
846 |
} catch (BadLocationException e) { |
847 |
JavaPlugin.log(e); |
848 |
} |
849 |
} |
850 |
return JavaHeuristicScanner.NOT_FOUND; |
851 |
} |
852 |
|
853 |
/** |
854 |
* Returns the reference position regarding to indentation for <code>position</code>, or |
855 |
* <code>NOT_FOUND</code>.<code>fIndent</code> will contain the relative indentation (in |
856 |
* indentation units, not characters) after the call. If there is a special alignment (e.g. for |
857 |
* a method declaration where parameters should be aligned), <code>fAlign</code> will contain |
858 |
* the absolute position of the alignment reference in <code>fDocument</code>, otherwise |
859 |
* <code>fAlign</code> is set to <code>JavaHeuristicScanner.NOT_FOUND</code>. This method calls |
860 |
* {@link #findReferencePosition(int, boolean, boolean, boolean, boolean, boolean) |
861 |
* findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, throwsClause)} |
862 |
* where <code>throwsClause</code> indicates whether a throws clause was found at |
863 |
* <code>position</code>. |
864 |
* |
818 |
* @param offset the offset for which the reference is computed |
865 |
* @param offset the offset for which the reference is computed |
819 |
* @param danglingElse whether a dangling else should be assumed at <code>position</code> |
866 |
* @param danglingElse whether a dangling else should be assumed at <code>position</code> |
820 |
* @param matchBrace whether the position of the matching brace should be |
867 |
* @param matchBrace whether the position of the matching brace should be returned instead of |
821 |
* returned instead of doing code analysis |
868 |
* doing code analysis |
822 |
* @param matchParen whether the position of the matching parenthesis |
869 |
* @param matchParen whether the position of the matching parenthesis should be returned instead |
823 |
* should be returned instead of doing code analysis |
870 |
* of doing code analysis |
824 |
* @param matchCase whether the position of a switch statement reference |
871 |
* @param matchCase whether the position of a switch statement reference should be returned |
825 |
* should be returned (either an earlier case statement or the |
872 |
* (either an earlier case statement or the switch block brace) |
826 |
* switch block brace) |
873 |
* @return the reference statement relative to which <code>position</code> should be indented, |
827 |
* @return the reference statement relative to which <code>position</code> |
874 |
* or {@link JavaHeuristicScanner#NOT_FOUND} |
828 |
* should be indented, or {@link JavaHeuristicScanner#NOT_FOUND} |
|
|
829 |
*/ |
875 |
*/ |
830 |
public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen, boolean matchCase) { |
876 |
public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen, boolean matchCase) { |
|
|
877 |
return findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, false); |
878 |
} |
879 |
|
880 |
/** |
881 |
* Returns the reference position regarding to indentation for <code>position</code>, or |
882 |
* <code>NOT_FOUND</code>.<code>fIndent</code> will contain the relative indentation (in |
883 |
* indentation units, not characters) after the call. If there is a special alignment (e.g. for |
884 |
* a method declaration where parameters should be aligned), <code>fAlign</code> will contain |
885 |
* the absolute position of the alignment reference in <code>fDocument</code>, otherwise |
886 |
* <code>fAlign</code> is set to <code>JavaHeuristicScanner.NOT_FOUND</code>. |
887 |
* |
888 |
* @param offset the offset for which the reference is computed |
889 |
* @param danglingElse whether a dangling else should be assumed at <code>position</code> |
890 |
* @param matchBrace whether the position of the matching brace should be returned instead of |
891 |
* doing code analysis |
892 |
* @param matchParen whether the position of the matching parenthesis should be returned instead |
893 |
* of doing code analysis |
894 |
* @param matchCase whether the position of a switch statement reference should be returned |
895 |
* (either an earlier case statement or the switch block brace) |
896 |
* @param throwsClause whether a throws clause was found at <code>position</code> |
897 |
* @return the reference statement relative to which <code>position</code> should be indented, |
898 |
* or {@link JavaHeuristicScanner#NOT_FOUND} |
899 |
* @since 3.7 |
900 |
*/ |
901 |
public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen, boolean matchCase, boolean throwsClause) { |
831 |
fIndent= 0; // the indentation modification |
902 |
fIndent= 0; // the indentation modification |
832 |
fAlign= JavaHeuristicScanner.NOT_FOUND; |
903 |
fAlign= JavaHeuristicScanner.NOT_FOUND; |
833 |
fPosition= offset; |
904 |
fPosition= offset; |
Lines 853-859
Link Here
|
853 |
} else { |
924 |
} else { |
854 |
// if we can't find the matching brace, the heuristic is to unindent |
925 |
// if we can't find the matching brace, the heuristic is to unindent |
855 |
// by one against the normal position |
926 |
// by one against the normal position |
856 |
int pos= findReferencePosition(offset, danglingElse, false, matchParen, matchCase); |
927 |
int pos= findReferencePosition(offset, danglingElse, false, matchParen, matchCase, throwsClause); |
857 |
fIndent--; |
928 |
fIndent--; |
858 |
return pos; |
929 |
return pos; |
859 |
} |
930 |
} |
Lines 866-872
Link Here
|
866 |
else { |
937 |
else { |
867 |
// if we can't find the matching paren, the heuristic is to unindent |
938 |
// if we can't find the matching paren, the heuristic is to unindent |
868 |
// by one against the normal position |
939 |
// by one against the normal position |
869 |
int pos= findReferencePosition(offset, danglingElse, matchBrace, false, matchCase); |
940 |
int pos= findReferencePosition(offset, danglingElse, matchBrace, false, matchCase, throwsClause); |
870 |
fIndent--; |
941 |
fIndent--; |
871 |
return pos; |
942 |
return pos; |
872 |
} |
943 |
} |
Lines 887-899
Link Here
|
887 |
int pos= fPosition; |
958 |
int pos= fPosition; |
888 |
if (!skipScope()) |
959 |
if (!skipScope()) |
889 |
fPosition= pos; |
960 |
fPosition= pos; |
890 |
//$FALL-THROUGH$ |
961 |
return skipToStatementStart(danglingElse, false); |
891 |
case Symbols.TokenSEMICOLON: |
962 |
case Symbols.TokenSEMICOLON: |
892 |
// this is the 90% case: after a statement block |
963 |
// this is the 90% case: after a statement block |
893 |
// the end of the previous statement / block previous.end |
964 |
// the end of the previous statement / block previous.end |
894 |
// search to the end of the statement / block before the previous; the token just after that is previous.start |
965 |
// search to the end of the statement / block before the previous; the token just after that is previous.start |
895 |
return skipToStatementStart(danglingElse, false); |
966 |
pos= fPosition; |
896 |
|
967 |
if (isForStatement()) { |
|
|
968 |
fIndent= fPrefs.prefContinuationIndent; |
969 |
return fPosition; |
970 |
} else { |
971 |
fPosition= pos; |
972 |
return skipToStatementStart(danglingElse, false); |
973 |
} |
897 |
// scope introduction: special treat who special is |
974 |
// scope introduction: special treat who special is |
898 |
case Symbols.TokenLPAREN: |
975 |
case Symbols.TokenLPAREN: |
899 |
case Symbols.TokenLBRACE: |
976 |
case Symbols.TokenLBRACE: |
Lines 906-913
Link Here
|
906 |
|
983 |
|
907 |
case Symbols.TokenEQUAL: |
984 |
case Symbols.TokenEQUAL: |
908 |
// indent assignments |
985 |
// indent assignments |
909 |
fIndent= fPrefs.prefAssignmentIndent; |
986 |
return handleEqual(); |
910 |
return fPosition; |
|
|
911 |
|
987 |
|
912 |
case Symbols.TokenCOLON: |
988 |
case Symbols.TokenCOLON: |
913 |
// TODO handle ternary deep indentation |
989 |
// TODO handle ternary deep indentation |
Lines 932-938
Link Here
|
932 |
|
1008 |
|
933 |
case Symbols.TokenTRY: |
1009 |
case Symbols.TokenTRY: |
934 |
return skipToStatementStart(danglingElse, false); |
1010 |
return skipToStatementStart(danglingElse, false); |
|
|
1011 |
|
1012 |
case Symbols.TokenRBRACKET: |
1013 |
fIndent= fPrefs.prefContinuationIndent; |
1014 |
return fPosition; |
1015 |
|
935 |
case Symbols.TokenRPAREN: |
1016 |
case Symbols.TokenRPAREN: |
|
|
1017 |
if (throwsClause) { |
1018 |
fIndent= fPrefs.prefContinuationIndent; |
1019 |
return fPosition; |
1020 |
} |
936 |
int line= fLine; |
1021 |
int line= fLine; |
937 |
if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) { |
1022 |
if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) { |
938 |
int scope= fPosition; |
1023 |
int scope= fPosition; |
Lines 958-963
Link Here
|
958 |
fLine= line; |
1043 |
fLine= line; |
959 |
|
1044 |
|
960 |
return skipToPreviousListItemOrListStart(); |
1045 |
return skipToPreviousListItemOrListStart(); |
|
|
1046 |
case Symbols.TokenRETURN: |
1047 |
fIndent= fPrefs.prefContinuationIndent; |
1048 |
return fPosition; |
961 |
case Symbols.TokenCOMMA: |
1049 |
case Symbols.TokenCOMMA: |
962 |
// inside a list of some type |
1050 |
// inside a list of some type |
963 |
// easy if there is already a list item before with its own indentation - we just align |
1051 |
// easy if there is already a list item before with its own indentation - we just align |
Lines 972-977
Link Here
|
972 |
} |
1060 |
} |
973 |
|
1061 |
|
974 |
/** |
1062 |
/** |
|
|
1063 |
* Checks if the statement at position is itself a continuation of the previous, else sets the |
1064 |
* indentation to Continuation Indent. |
1065 |
* |
1066 |
* @return the position of the token |
1067 |
* @since 3.7 |
1068 |
*/ |
1069 |
private int handleEqual() { |
1070 |
try { |
1071 |
//If this line is itself continuation of the previous then do nothing |
1072 |
IRegion line= fDocument.getLineInformationOfOffset(fPosition); |
1073 |
int nonWS= fScanner.findNonWhitespaceBackward(line.getOffset(), JavaHeuristicScanner.UNBOUND); |
1074 |
if (nonWS != Symbols.TokenEOF) { |
1075 |
int tokenAtPreviousLine= fScanner.nextToken(nonWS, nonWS + 1); |
1076 |
if (tokenAtPreviousLine != Symbols.TokenSEMICOLON && tokenAtPreviousLine != Symbols.TokenRBRACE && tokenAtPreviousLine != Symbols.TokenLBRACE |
1077 |
&& tokenAtPreviousLine != Symbols.TokenEOF) |
1078 |
return fPosition; |
1079 |
} |
1080 |
} catch (BadLocationException e) { |
1081 |
return fPosition; |
1082 |
} |
1083 |
|
1084 |
fIndent= fPrefs.prefContinuationIndent; |
1085 |
return fPosition; |
1086 |
} |
1087 |
|
1088 |
/** |
1089 |
* Checks if the semicolon at the current position is part of a for statement. |
1090 |
* |
1091 |
* @return returns <code>true</code> if current position is part of for statement |
1092 |
* @since 3.7 |
1093 |
*/ |
1094 |
private boolean isForStatement() { |
1095 |
int semiColonCount= 1; |
1096 |
while (true) { |
1097 |
nextToken(); |
1098 |
switch (fToken) { |
1099 |
case Symbols.TokenFOR: |
1100 |
return true; |
1101 |
case Symbols.TokenLBRACE: |
1102 |
return false; |
1103 |
case Symbols.TokenSEMICOLON: |
1104 |
semiColonCount++; |
1105 |
if (semiColonCount > 2) |
1106 |
return false; |
1107 |
break; |
1108 |
case Symbols.TokenEOF: |
1109 |
return false; |
1110 |
} |
1111 |
} |
1112 |
} |
1113 |
|
1114 |
/** |
975 |
* Skips to the start of a statement that ends at the current position. |
1115 |
* Skips to the start of a statement that ends at the current position. |
976 |
* |
1116 |
* |
977 |
* @param danglingElse whether to indent aligned with the last <code>if</code> |
1117 |
* @param danglingElse whether to indent aligned with the last <code>if</code> |
Lines 1235-1240
Link Here
|
1235 |
return handleScopeIntroduction(startPosition + 1); |
1375 |
return handleScopeIntroduction(startPosition + 1); |
1236 |
|
1376 |
|
1237 |
case Symbols.TokenSEMICOLON: |
1377 |
case Symbols.TokenSEMICOLON: |
|
|
1378 |
int savedPosition= fPosition; |
1379 |
if (isForStatement()) |
1380 |
fIndent= fPrefs.prefContinuationIndent; |
1381 |
else |
1382 |
fPosition= savedPosition; |
1238 |
return fPosition; |
1383 |
return fPosition; |
1239 |
case Symbols.TokenQUESTIONMARK: |
1384 |
case Symbols.TokenQUESTIONMARK: |
1240 |
if (fPrefs.prefTernaryDeepAlign) { |
1385 |
if (fPrefs.prefTernaryDeepAlign) { |
Lines 1244-1249
Link Here
|
1244 |
fIndent= fPrefs.prefTernaryIndent; |
1389 |
fIndent= fPrefs.prefTernaryIndent; |
1245 |
return fPosition; |
1390 |
return fPosition; |
1246 |
} |
1391 |
} |
|
|
1392 |
case Symbols.TokenRETURN: |
1393 |
fIndent= fPrefs.prefContinuationIndent; |
1394 |
return fPosition; |
1395 |
case Symbols.TokenEQUAL: |
1396 |
return handleEqual(); |
1247 |
case Symbols.TokenEOF: |
1397 |
case Symbols.TokenEOF: |
1248 |
return 0; |
1398 |
return 0; |
1249 |
|
1399 |
|