mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 383277 - Invalid auto indentation before and after colon in class
declaration with inheritance
This commit is contained in:
parent
5eb8410fbd
commit
bac3846b32
4 changed files with 201 additions and 104 deletions
|
@ -40,7 +40,6 @@ import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
import org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy;
|
import org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy;
|
||||||
|
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy;
|
import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy;
|
||||||
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
||||||
|
|
||||||
|
@ -270,28 +269,28 @@ public class CAutoIndentTest extends AbstractAutoEditTest {
|
||||||
String[] kw_inh= new String[] {"class", "union", "struct"};
|
String[] kw_inh= new String[] {"class", "union", "struct"};
|
||||||
String[] kw_anon= new String[] {"union", "struct", "enum"};
|
String[] kw_anon= new String[] {"union", "struct", "enum"};
|
||||||
|
|
||||||
for(int i=0; i<kw.length; i++) {
|
for (int i= 0; i < kw.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n\n\n "+kw[i]+" A {\n"); //$NON-NLS-1$
|
tester.type("\n\n\n "+kw[i]+" A {\n"); //$NON-NLS-1$
|
||||||
assertEquals("\n\n\n "+kw[i]+" A {\n\t \n };", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n\n\n "+kw[i]+" A {\n\t \n };", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<kw.length; i++) {
|
for (int i= 0; i < kw.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n\n\n"+kw[i]+" A {\n"); //$NON-NLS-1$
|
tester.type("\n\n\n"+kw[i]+" A {\n"); //$NON-NLS-1$
|
||||||
assertEquals("\n\n\n"+kw[i]+" A {\n\t\n};", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n\n\n"+kw[i]+" A {\n\t\n};", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<kw.length; i++) {
|
for (int i= 0; i < kw.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n\n\n "+kw[i]+" A {\n"); //$NON-NLS-1$
|
tester.type("\n\n\n "+kw[i]+" A {\n"); //$NON-NLS-1$
|
||||||
assertEquals("\n\n\n "+kw[i]+" A {\n\t \n };", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n\n\n "+kw[i]+" A {\n\t \n };", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<kw.length; i++) {
|
for (int i= 0; i < kw.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n// foo\n\n\n//bar\n\n"); //$NON-NLS-1$
|
tester.type("\n// foo\n\n\n//bar\n\n"); //$NON-NLS-1$
|
||||||
|
@ -300,17 +299,17 @@ public class CAutoIndentTest extends AbstractAutoEditTest {
|
||||||
assertEquals("\n// foo\n"+kw[i]+" A {\n\t\n};\n\n//bar\n\n", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n// foo\n"+kw[i]+" A {\n\t\n};\n\n//bar\n\n", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
// this tests for a sensible behaviour for enums, although the
|
// this tests for a sensible behavior for enums, although the
|
||||||
// code generated is invalid, its the user entered part that is
|
// code generated is invalid, its the user entered part that is
|
||||||
// the problem
|
// the problem
|
||||||
for(int i=0; i<kw_inh.length; i++) {
|
for (int i= 0; i < kw_inh.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n\n\n"+kw_inh[i]+" A\n:\npublic B\n,\npublic C\n{\n"); //$NON-NLS-1$
|
tester.type("\n\n\n"+kw_inh[i]+" A\n:\npublic B\n,\npublic C\n{\n"); //$NON-NLS-1$
|
||||||
assertEquals("\n\n\n"+kw_inh[i]+" A\n:\n\tpublic B\n\t,\n\tpublic C\n\t{\n\t\t\n\t};", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n\n\n"+kw_inh[i]+" A\n:\n\t\tpublic B\n\t\t,\n\t\tpublic C\n{\n\t\n};", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<kw.length; i++) {
|
for (int i= 0; i < kw.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n// foo\n\n\n//bar\n\n"); //$NON-NLS-1$
|
tester.type("\n// foo\n\n\n//bar\n\n"); //$NON-NLS-1$
|
||||||
|
@ -319,13 +318,13 @@ public class CAutoIndentTest extends AbstractAutoEditTest {
|
||||||
assertEquals("\n// foo\n"+kw[i]+" /* for(int i=0; i<100; i++) {} */\nA \n{\n\t\n};\n\n//bar\n\n", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n// foo\n"+kw[i]+" /* for(int i=0; i<100; i++) {} */\nA \n{\n\t\n};\n\n//bar\n\n", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<kw_anon.length; i++) {
|
for (int i= 0; i < kw_anon.length; i++) {
|
||||||
tester.reset();
|
tester.reset();
|
||||||
|
|
||||||
tester.type("\n\n\n"+kw_anon[i]+" {\n"); //$NON-NLS-1$
|
tester.type("\n\n\n"+kw_anon[i]+" {\n"); //$NON-NLS-1$
|
||||||
assertEquals("\n\n\n"+kw_anon[i]+" {\n\t\n};", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("\n\n\n"+kw_anon[i]+" {\n\t\n};", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that brackets are inserted (without semi-colons) in appropriate
|
* Tests that brackets are inserted (without semi-colons) in appropriate
|
||||||
|
|
|
@ -460,6 +460,32 @@ public class CIndenterTest extends BaseUITestCase {
|
||||||
assertIndenterResult();
|
assertIndenterResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//class ClassWithLongName :
|
||||||
|
//public AnotherClassWithLongName,
|
||||||
|
//protected YetAnotherClassWithLongName
|
||||||
|
//{
|
||||||
|
//};
|
||||||
|
//class ClassWithLongName
|
||||||
|
//: public AnotherClassWithLongName,
|
||||||
|
//protected YetAnotherClassWithLongName
|
||||||
|
//{
|
||||||
|
//};
|
||||||
|
|
||||||
|
//class ClassWithLongName :
|
||||||
|
// public AnotherClassWithLongName,
|
||||||
|
// protected YetAnotherClassWithLongName
|
||||||
|
//{
|
||||||
|
//};
|
||||||
|
//class ClassWithLongName
|
||||||
|
// : public AnotherClassWithLongName,
|
||||||
|
// protected YetAnotherClassWithLongName
|
||||||
|
//{
|
||||||
|
//};
|
||||||
|
public void testBaseClause_Bug383277() throws Exception {
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
|
||||||
|
assertIndenterResult();
|
||||||
|
}
|
||||||
|
|
||||||
//namespace ns {
|
//namespace ns {
|
||||||
//class A;
|
//class A;
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
|
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
|
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CIndenter.MatchMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto indent strategy sensitive to brackets.
|
* Auto indent strategy sensitive to brackets.
|
||||||
|
@ -183,7 +184,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
// shift only when line does not contain any text up to the closing bracket
|
// shift only when line does not contain any text up to the closing bracket
|
||||||
if (whiteend == c.offset) {
|
if (whiteend == c.offset) {
|
||||||
// evaluate the line with the opening bracket that matches out closing bracket
|
// evaluate the line with the opening bracket that matches out closing bracket
|
||||||
int reference = indenter.findReferencePosition(c.offset, false, true, false, false, false);
|
int reference = indenter.findReferencePosition(c.offset, false, MatchMode.MATCH_BRACE);
|
||||||
int indLine = d.getLineOfOffset(reference);
|
int indLine = d.getLineOfOffset(reference);
|
||||||
if (indLine != -1 && indLine != line) {
|
if (indLine != -1 && indLine != line) {
|
||||||
// take the indent of the found line
|
// take the indent of the found line
|
||||||
|
@ -219,7 +220,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
int lineOffset = d.getLineOffset(line);
|
int lineOffset = d.getLineOffset(line);
|
||||||
|
|
||||||
// make sure we don't have any leading comments etc.
|
// make sure we don't have any leading comments etc.
|
||||||
if (d.get(lineOffset, c.offset - lineOffset).trim().length() != 0)
|
if (!d.get(lineOffset, c.offset - lineOffset).trim().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Line of last C code
|
// Line of last C code
|
||||||
|
@ -851,7 +852,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
case Symbols.TokenDEFAULT:
|
case Symbols.TokenDEFAULT:
|
||||||
{
|
{
|
||||||
CIndenter indenter= new CIndenter(document, dScanner, fProject);
|
CIndenter indenter= new CIndenter(document, dScanner, fProject);
|
||||||
peer= indenter.findReferencePosition(dPos, false, false, false, true, false);
|
peer= indenter.findReferencePosition(dPos, false, MatchMode.MATCH_CASE);
|
||||||
if (peer == CHeuristicScanner.NOT_FOUND)
|
if (peer == CHeuristicScanner.NOT_FOUND)
|
||||||
return firstPeer;
|
return firstPeer;
|
||||||
firstPeer= peer;
|
firstPeer= peer;
|
||||||
|
@ -863,7 +864,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
case Symbols.TokenPRIVATE:
|
case Symbols.TokenPRIVATE:
|
||||||
{
|
{
|
||||||
CIndenter indenter= new CIndenter(document, dScanner, fProject);
|
CIndenter indenter= new CIndenter(document, dScanner, fProject);
|
||||||
peer= indenter.findReferencePosition(dPos, false, false, false, false, true);
|
peer= indenter.findReferencePosition(dPos, false, MatchMode.MATCH_ACCESS_SPECIFIER);
|
||||||
if (peer == CHeuristicScanner.NOT_FOUND)
|
if (peer == CHeuristicScanner.NOT_FOUND)
|
||||||
return firstPeer;
|
return firstPeer;
|
||||||
firstPeer= peer;
|
firstPeer= peer;
|
||||||
|
@ -969,7 +970,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
// Only shift if the last C line is further up and is a braceless block candidate
|
// Only shift if the last C line is further up and is a braceless block candidate
|
||||||
if (lastLine < line) {
|
if (lastLine < line) {
|
||||||
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
||||||
int ref = indenter.findReferencePosition(p, true, false, false, false, false);
|
int ref = indenter.findReferencePosition(p, true, MatchMode.REGULAR);
|
||||||
if (ref == CHeuristicScanner.NOT_FOUND)
|
if (ref == CHeuristicScanner.NOT_FOUND)
|
||||||
return;
|
return;
|
||||||
int refLine = doc.getLineOfOffset(ref);
|
int refLine = doc.getLineOfOffset(ref);
|
||||||
|
@ -1006,7 +1007,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
// Only shift if the last C line is further up and is a braceless block candidate
|
// Only shift if the last C line is further up and is a braceless block candidate
|
||||||
if (lastLine < line) {
|
if (lastLine < line) {
|
||||||
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
||||||
int ref = indenter.findReferencePosition(p, false, false, false, true, false);
|
int ref = indenter.findReferencePosition(p, false, MatchMode.MATCH_CASE);
|
||||||
if (ref == CHeuristicScanner.NOT_FOUND)
|
if (ref == CHeuristicScanner.NOT_FOUND)
|
||||||
return;
|
return;
|
||||||
int refLine = doc.getLineOfOffset(ref);
|
int refLine = doc.getLineOfOffset(ref);
|
||||||
|
@ -1069,9 +1070,9 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
CIndenter indenter = new CIndenter(doc, scanner, fProject);
|
||||||
int ref;
|
int ref;
|
||||||
if (prevToken == Symbols.TokenDEFAULT)
|
if (prevToken == Symbols.TokenDEFAULT)
|
||||||
ref = indenter.findReferencePosition(p, false, false, false, true, false);
|
ref = indenter.findReferencePosition(p, false, MatchMode.MATCH_CASE);
|
||||||
else
|
else
|
||||||
ref = indenter.findReferencePosition(p, false, false, false, false, true);
|
ref = indenter.findReferencePosition(p, false, MatchMode.MATCH_ACCESS_SPECIFIER);
|
||||||
if (ref == CHeuristicScanner.NOT_FOUND)
|
if (ref == CHeuristicScanner.NOT_FOUND)
|
||||||
return;
|
return;
|
||||||
int refLine = doc.getLineOfOffset(ref);
|
int refLine = doc.getLineOfOffset(ref);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.internal.ui.text.CHeuristicScanner.NOT_FOUND;
|
||||||
|
|
||||||
import org.eclipse.core.resources.ProjectScope;
|
import org.eclipse.core.resources.ProjectScope;
|
||||||
import org.eclipse.core.runtime.Assert;
|
import org.eclipse.core.runtime.Assert;
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
@ -386,7 +388,7 @@ public final class CIndenter {
|
||||||
private int fExtraSpaces;
|
private int fExtraSpaces;
|
||||||
/**
|
/**
|
||||||
* The absolute (character-counted) indentation offset for special cases
|
* The absolute (character-counted) indentation offset for special cases
|
||||||
* (method defs, array initializers)
|
* (method definitions, array initializers)
|
||||||
*/
|
*/
|
||||||
private int fAlign;
|
private int fAlign;
|
||||||
/** The stateful scan position for the indentation methods. */
|
/** The stateful scan position for the indentation methods. */
|
||||||
|
@ -458,14 +460,11 @@ public final class CIndenter {
|
||||||
* if it cannot be determined
|
* if it cannot be determined
|
||||||
*/
|
*/
|
||||||
private StringBuilder getReferenceIndentation(int offset, boolean assumeOpeningBrace) {
|
private StringBuilder getReferenceIndentation(int offset, boolean assumeOpeningBrace) {
|
||||||
int unit;
|
int unit= findReferencePosition(offset,
|
||||||
if (assumeOpeningBrace)
|
assumeOpeningBrace ? Symbols.TokenLBRACE : peekToken(offset));
|
||||||
unit= findReferencePosition(offset, Symbols.TokenLBRACE);
|
|
||||||
else
|
|
||||||
unit= findReferencePosition(offset, peekToken(offset));
|
|
||||||
|
|
||||||
// if we were unable to find anything, return null
|
// if we were unable to find anything, return null
|
||||||
if (unit == CHeuristicScanner.NOT_FOUND)
|
if (unit == NOT_FOUND)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return getLeadingWhitespace(unit);
|
return getLeadingWhitespace(unit);
|
||||||
|
@ -496,7 +495,7 @@ public final class CIndenter {
|
||||||
StringBuilder reference= getReferenceIndentation(offset, assumeOpeningBrace);
|
StringBuilder reference= getReferenceIndentation(offset, assumeOpeningBrace);
|
||||||
|
|
||||||
// handle special alignment
|
// handle special alignment
|
||||||
if (fAlign != CHeuristicScanner.NOT_FOUND) {
|
if (fAlign != NOT_FOUND) {
|
||||||
try {
|
try {
|
||||||
// a special case has been detected.
|
// a special case has been detected.
|
||||||
IRegion line= fDocument.getLineInformationOfOffset(fAlign);
|
IRegion line= fDocument.getLineInformationOfOffset(fAlign);
|
||||||
|
@ -717,13 +716,13 @@ public final class CIndenter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the reference position regarding to indentation for <code>offset</code>,
|
* Returns the reference position regarding to indentation for <code>offset</code>,
|
||||||
* or <code>NOT_FOUND</code>. This method calls
|
* or {@link CHeuristicScanner#NOT_FOUND NOT_FOUND}. This method calls
|
||||||
* {@link #findReferencePosition(int, int) findReferencePosition(offset, nextChar)} where
|
* {@link #findReferencePosition(int, int) findReferencePosition(offset, nextChar)} where
|
||||||
* <code>nextChar</code> is the next character after <code>offset</code>.
|
* <code>nextChar</code> is the next character after <code>offset</code>.
|
||||||
*
|
*
|
||||||
* @param offset the offset for which the reference is computed
|
* @param offset the offset for which the reference is computed
|
||||||
* @return the reference statement relative to which <code>offset</code>
|
* @return the reference statement relative to which <code>offset</code>
|
||||||
* should be indented, or {@link CHeuristicScanner#NOT_FOUND}
|
* should be indented, or {@link CHeuristicScanner#NOT_FOUND NOT_FOUND}
|
||||||
*/
|
*/
|
||||||
public int findReferencePosition(int offset) {
|
public int findReferencePosition(int offset) {
|
||||||
return findReferencePosition(offset, peekToken(offset));
|
return findReferencePosition(offset, peekToken(offset));
|
||||||
|
@ -740,8 +739,29 @@ public final class CIndenter {
|
||||||
if (offset < fDocument.getLength()) {
|
if (offset < fDocument.getLength()) {
|
||||||
try {
|
try {
|
||||||
IRegion line= fDocument.getLineInformationOfOffset(offset);
|
IRegion line= fDocument.getLineInformationOfOffset(offset);
|
||||||
int lineOffset= line.getOffset();
|
int lineEnd= line.getOffset() + line.getLength();
|
||||||
int next= fScanner.nextToken(offset, lineOffset + line.getLength());
|
int next= fScanner.nextToken(offset, lineEnd);
|
||||||
|
return next;
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Symbols.TokenEOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peeks the second next token in the document that comes after <code>offset</code>
|
||||||
|
* on the same line as <code>offset</code>.
|
||||||
|
*
|
||||||
|
* @param offset the offset into document
|
||||||
|
* @return the token symbol of the second next element, or TokenEOF if there is none
|
||||||
|
*/
|
||||||
|
private int peekSecondToken(int offset) {
|
||||||
|
if (offset < fDocument.getLength()) {
|
||||||
|
try {
|
||||||
|
IRegion line= fDocument.getLineInformationOfOffset(offset);
|
||||||
|
int lineEnd= line.getOffset() + line.getLength();
|
||||||
|
fScanner.nextToken(offset, lineEnd);
|
||||||
|
int next = fScanner.nextToken(fScanner.getPosition(), lineEnd);
|
||||||
return next;
|
return next;
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
}
|
}
|
||||||
|
@ -751,7 +771,7 @@ public final class CIndenter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the reference position regarding to indentation for <code>position</code>,
|
* Returns the reference position regarding to indentation for <code>position</code>,
|
||||||
* or <code>NOT_FOUND</code>.
|
* or {@link CHeuristicScanner#NOT_FOUND NOT_FOUND}.
|
||||||
*
|
*
|
||||||
* <p>If <code>peekNextChar</code> is <code>true</code>, the next token after
|
* <p>If <code>peekNextChar</code> is <code>true</code>, the next token after
|
||||||
* <code>offset</code> is read and taken into account when computing the
|
* <code>offset</code> is read and taken into account when computing the
|
||||||
|
@ -773,16 +793,13 @@ public final class CIndenter {
|
||||||
* @param offset the offset for which the reference is computed
|
* @param offset the offset for which the reference is computed
|
||||||
* @param nextToken the next token to assume in the document
|
* @param nextToken the next token to assume in the document
|
||||||
* @return the reference statement relative to which <code>offset</code>
|
* @return the reference statement relative to which <code>offset</code>
|
||||||
* should be indented, or {@link CHeuristicScanner#NOT_FOUND}
|
* should be indented, or {@link CHeuristicScanner#NOT_FOUND NOT_FOUND}
|
||||||
*/
|
*/
|
||||||
public int findReferencePosition(int offset, int nextToken) {
|
public int findReferencePosition(int offset, int nextToken) {
|
||||||
boolean danglingElse= false;
|
boolean danglingElse= false;
|
||||||
boolean cancelIndent= false; // If set to true, fIndent is ignored.
|
boolean cancelIndent= false; // If set to true, fIndent is ignored.
|
||||||
int extraIndent= 0; // Can be either positive or negative.
|
int extraIndent= 0; // Can be either positive or negative.
|
||||||
boolean matchBrace= false;
|
MatchMode matchMode = MatchMode.REGULAR;
|
||||||
boolean matchParen= false;
|
|
||||||
boolean matchCase= false;
|
|
||||||
boolean matchAccessSpecifier= false;
|
|
||||||
|
|
||||||
// Account for un-indentation characters already typed in, but after position.
|
// Account for un-indentation characters already typed in, but after position.
|
||||||
// If they are on a line by themselves, the indentation gets adjusted accordingly.
|
// If they are on a line by themselves, the indentation gets adjusted accordingly.
|
||||||
|
@ -793,7 +810,8 @@ public final class CIndenter {
|
||||||
IRegion line= fDocument.getLineInformationOfOffset(offset);
|
IRegion line= fDocument.getLineInformationOfOffset(offset);
|
||||||
int lineOffset= line.getOffset();
|
int lineOffset= line.getOffset();
|
||||||
int prevPos= Math.max(offset - 1, 0);
|
int prevPos= Math.max(offset - 1, 0);
|
||||||
boolean isFirstTokenOnLine= fDocument.get(lineOffset, prevPos + 1 - lineOffset).trim().length() == 0;
|
boolean isFirstTokenOnLine=
|
||||||
|
fDocument.get(lineOffset, prevPos + 1 - lineOffset).trim().length() == 0;
|
||||||
int prevToken= fScanner.previousToken(prevPos, CHeuristicScanner.UNBOUND);
|
int prevToken= fScanner.previousToken(prevPos, CHeuristicScanner.UNBOUND);
|
||||||
boolean bracelessBlockStart= fScanner.isBracelessBlockStart(prevPos, CHeuristicScanner.UNBOUND);
|
boolean bracelessBlockStart= fScanner.isBracelessBlockStart(prevPos, CHeuristicScanner.UNBOUND);
|
||||||
|
|
||||||
|
@ -805,14 +823,14 @@ public final class CIndenter {
|
||||||
case Symbols.TokenCASE:
|
case Symbols.TokenCASE:
|
||||||
case Symbols.TokenDEFAULT:
|
case Symbols.TokenDEFAULT:
|
||||||
if (isFirstTokenOnLine)
|
if (isFirstTokenOnLine)
|
||||||
matchCase= true;
|
matchMode = MatchMode.MATCH_CASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Symbols.TokenPUBLIC:
|
case Symbols.TokenPUBLIC:
|
||||||
case Symbols.TokenPROTECTED:
|
case Symbols.TokenPROTECTED:
|
||||||
case Symbols.TokenPRIVATE:
|
case Symbols.TokenPRIVATE:
|
||||||
if (isFirstTokenOnLine)
|
if (isFirstTokenOnLine && peekSecondToken(offset) != Symbols.TokenIDENT)
|
||||||
matchAccessSpecifier= true;
|
matchMode = MatchMode.MATCH_ACCESS_SPECIFIER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Symbols.TokenLBRACE: // for opening-brace-on-new-line style
|
case Symbols.TokenLBRACE: // for opening-brace-on-new-line style
|
||||||
|
@ -825,34 +843,41 @@ public final class CIndenter {
|
||||||
cancelIndent= true;
|
cancelIndent= true;
|
||||||
} else if ((prevToken == Symbols.TokenRPAREN || prevToken == Symbols.TokenCONST) && fPrefs.prefIndentBracesForMethods) {
|
} else if ((prevToken == Symbols.TokenRPAREN || prevToken == Symbols.TokenCONST) && fPrefs.prefIndentBracesForMethods) {
|
||||||
extraIndent= 1;
|
extraIndent= 1;
|
||||||
} else if (prevToken == Symbols.TokenIDENT && fPrefs.prefIndentBracesForTypes) {
|
} else if (prevToken == Symbols.TokenIDENT) {
|
||||||
extraIndent= 1;
|
if (fPrefs.prefIndentBracesForTypes) {
|
||||||
|
extraIndent= 1;
|
||||||
|
}
|
||||||
|
int pos = fPosition;
|
||||||
|
fPosition = offset;
|
||||||
|
if (matchTypeDeclaration() != NOT_FOUND) {
|
||||||
|
matchMode = MatchMode.MATCH_TYPE_DECLARATION;
|
||||||
|
}
|
||||||
|
fPosition = pos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Symbols.TokenRBRACE: // closing braces get unindented
|
case Symbols.TokenRBRACE: // closing braces get unindented
|
||||||
if (isFirstTokenOnLine || prevToken != Symbols.TokenLBRACE)
|
if (isFirstTokenOnLine || prevToken != Symbols.TokenLBRACE)
|
||||||
matchBrace= true;
|
matchMode = MatchMode.MATCH_BRACE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Symbols.TokenRPAREN:
|
case Symbols.TokenRPAREN:
|
||||||
if (isFirstTokenOnLine)
|
if (isFirstTokenOnLine)
|
||||||
matchParen= true;
|
matchMode = MatchMode.MATCH_PAREN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// don't assume an else could come if we are at the end of file
|
// Don't assume an else could come if we are at the end of file.
|
||||||
danglingElse= false;
|
danglingElse= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase,
|
int ref= findReferencePosition(offset, danglingElse, matchMode);
|
||||||
matchAccessSpecifier);
|
|
||||||
if (cancelIndent) {
|
if (cancelIndent) {
|
||||||
fIndent = 0;
|
fIndent = 0;
|
||||||
} else if (extraIndent > 0) {
|
} else if (extraIndent > 0) {
|
||||||
fAlign= CHeuristicScanner.NOT_FOUND;
|
fAlign= NOT_FOUND;
|
||||||
fIndent += extraIndent;
|
fIndent += extraIndent;
|
||||||
} else {
|
} else {
|
||||||
fIndent += extraIndent;
|
fIndent += extraIndent;
|
||||||
|
@ -860,91 +885,130 @@ public final class CIndenter {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumeration used by {@link #findReferencePosition(int, boolean, MatchMode)} method.
|
||||||
|
*/
|
||||||
|
public enum MatchMode {
|
||||||
|
/**
|
||||||
|
* The reference position should be returned based on the regular code analysis.
|
||||||
|
*/
|
||||||
|
REGULAR,
|
||||||
|
/**
|
||||||
|
* The position of the matching brace should be returned instead of doing code analysis.
|
||||||
|
*/
|
||||||
|
MATCH_BRACE,
|
||||||
|
/**
|
||||||
|
* The position of the matching parenthesis should be returned instead of doing code
|
||||||
|
* analysis.
|
||||||
|
*/
|
||||||
|
MATCH_PAREN,
|
||||||
|
/**
|
||||||
|
* The position of a switch statement reference should be returned (either an earlier case
|
||||||
|
* statement or the switch block brace).
|
||||||
|
*/
|
||||||
|
MATCH_CASE,
|
||||||
|
/**
|
||||||
|
* The position of a class body reference should be returned (either an earlier
|
||||||
|
* public/protected/private or the class body brace).
|
||||||
|
*/
|
||||||
|
MATCH_ACCESS_SPECIFIER,
|
||||||
|
/**
|
||||||
|
* The position of a class declaration should be returned.
|
||||||
|
*/
|
||||||
|
MATCH_TYPE_DECLARATION
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the reference position regarding to indentation for <code>position</code>,
|
* Returns the reference position regarding to indentation for <code>position</code>,
|
||||||
* or <code>NOT_FOUND</code>.<code>fIndent</code> will contain the
|
* or {@link CHeuristicScanner#NOT_FOUND NOT_FOUND}. <code>fIndent</code> will contain
|
||||||
* relative indentation (in indentation units, not characters) after the
|
* the relative indentation (in indentation units, not characters) after the call. If there is
|
||||||
* call. If there is a special alignment (e.g. for a method declaration
|
* a special alignment (e.g. for a method declaration where parameters should be aligned),
|
||||||
* where parameters should be aligned), <code>fAlign</code> will contain
|
* <code>fAlign</code> will contain the absolute position of the alignment reference
|
||||||
* the absolute position of the alignment reference in <code>fDocument</code>,
|
* in <code>fDocument</code>, otherwise <code>fAlign</code> is set to
|
||||||
* otherwise <code>fAlign</code> is set to <code>CHeuristicScanner.NOT_FOUND</code>.
|
* {@link CHeuristicScanner#NOT_FOUND}.
|
||||||
*
|
*
|
||||||
* @param offset the offset for which the reference is computed
|
* @param offset the offset for which the reference is computed
|
||||||
* @param danglingElse whether a dangling else should be assumed at <code>position</code>
|
* @param danglingElse whether a dangling else should be assumed at <code>position</code>
|
||||||
* @param matchBrace whether the position of the matching brace should be
|
* @param matchMode determines what kind of reference position should be returned.
|
||||||
* returned instead of doing code analysis
|
* See {@link MatchMode}.
|
||||||
* @param matchParen whether the position of the matching parenthesis
|
|
||||||
* should be returned instead of doing code analysis
|
|
||||||
* @param matchCase whether the position of a switch statement reference
|
|
||||||
* should be returned (either an earlier case statement or the
|
|
||||||
* switch block brace)
|
|
||||||
* @param matchAccessSpecifier whether the position of a class body reference
|
|
||||||
* should be returned (either an earlier public/protected/private
|
|
||||||
* or the class body brace)
|
|
||||||
* @return the reference statement relative to which <code>position</code>
|
* @return the reference statement relative to which <code>position</code>
|
||||||
* should be indented, or {@link CHeuristicScanner#NOT_FOUND}
|
* should be indented, or {@link CHeuristicScanner#NOT_FOUND}
|
||||||
*/
|
*/
|
||||||
public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen,
|
public int findReferencePosition(int offset, boolean danglingElse, MatchMode matchMode) {
|
||||||
boolean matchCase, boolean matchAccessSpecifier) {
|
|
||||||
fIndent= 0; // The indentation modification
|
fIndent= 0; // The indentation modification
|
||||||
fExtraSpaces= 0;
|
fExtraSpaces= 0;
|
||||||
fAlign= CHeuristicScanner.NOT_FOUND;
|
fAlign= NOT_FOUND;
|
||||||
fPosition= offset;
|
fPosition= offset;
|
||||||
|
|
||||||
// forward cases
|
// Forward cases.
|
||||||
// An unindentation happens sometimes if the next token is special, namely on braces, parens and case
|
// An unindentation happens sometimes if the next token is special, namely on braces,
|
||||||
// labels align braces, but handle the case where we align with the method declaration start instead
|
// parens and case labels align braces, but handle the case where we align with the method
|
||||||
// of the opening brace.
|
// declaration start instead of the opening brace.
|
||||||
if (matchBrace) {
|
switch (matchMode) {
|
||||||
|
case MATCH_BRACE:
|
||||||
if (skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE)) {
|
if (skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE)) {
|
||||||
try {
|
try {
|
||||||
// Align with the opening brace that is on a line by its own
|
// Align with the opening brace that is on a line by its own
|
||||||
int lineOffset= fDocument.getLineOffset(fLine);
|
int lineOffset= fDocument.getLineOffset(fLine);
|
||||||
if (lineOffset <= fPosition && fDocument.get(lineOffset, fPosition - lineOffset).trim().length() == 0)
|
if (lineOffset <= fPosition &&
|
||||||
|
fDocument.get(lineOffset, fPosition - lineOffset).trim().isEmpty()) {
|
||||||
return fPosition;
|
return fPosition;
|
||||||
|
}
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
// Concurrent modification - walk default path
|
// Concurrent modification - walk default path
|
||||||
}
|
}
|
||||||
// If the opening brace is not on the start of the line, skip to the start
|
// If the opening brace is not on the start of the line, skip to the start.
|
||||||
int pos= skipToStatementStart(true, true);
|
int pos= skipToStatementStart(true, true);
|
||||||
fIndent= 0; // indent is aligned with reference position
|
fIndent= 0; // indent is aligned with reference position
|
||||||
return pos;
|
return pos;
|
||||||
} else {
|
} else {
|
||||||
// If we can't find the matching brace, the heuristic is to unindent
|
// If we can't find the matching brace, the heuristic is to unindent
|
||||||
// by one against the normal position
|
// by one against the normal position
|
||||||
int pos= findReferencePosition(offset, danglingElse, false, matchParen, matchCase,
|
int pos= findReferencePosition(offset, danglingElse, MatchMode.REGULAR);
|
||||||
matchAccessSpecifier);
|
|
||||||
fIndent--;
|
fIndent--;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Align parentheses
|
case MATCH_PAREN:
|
||||||
if (matchParen) {
|
// Align parentheses.
|
||||||
if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) {
|
if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) {
|
||||||
return fPosition;
|
return fPosition;
|
||||||
} else {
|
} else {
|
||||||
// if we can't find the matching paren, the heuristic is to unindent
|
// If we can't find the matching paren, the heuristic is to unindent by one
|
||||||
// by one against the normal position
|
// against the normal position.
|
||||||
int pos= findReferencePosition(offset, danglingElse, matchBrace, false, matchCase,
|
int pos= findReferencePosition(offset, danglingElse, MatchMode.REGULAR);
|
||||||
matchAccessSpecifier);
|
|
||||||
fIndent--;
|
fIndent--;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The only reliable way to get case labels aligned (due to many different styles of using braces in
|
case MATCH_CASE:
|
||||||
// a block) is to go for another case statement, or the scope opening brace.
|
// The only reliable way to get case labels aligned (due to many different styles of
|
||||||
if (matchCase) {
|
// using braces in a block) is to go for another case statement, or the scope opening
|
||||||
|
// brace.
|
||||||
return matchCaseAlignment();
|
return matchCaseAlignment();
|
||||||
|
|
||||||
|
case MATCH_ACCESS_SPECIFIER:
|
||||||
|
// The only reliable way to get access specifiers aligned (due to many different styles
|
||||||
|
// of using braces in a block) is to go for another access specifier, or the scope
|
||||||
|
// opening brace.
|
||||||
|
return matchAccessSpecifierAlignment();
|
||||||
|
|
||||||
|
case MATCH_TYPE_DECLARATION:
|
||||||
|
return matchTypeDeclaration();
|
||||||
|
|
||||||
|
case REGULAR:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the only reliable way to get access specifiers aligned (due to many different styles of using
|
if (peekToken(offset) == Symbols.TokenCOLON) {
|
||||||
// braces in a block) is to go for another access specifier, or the scope opening brace.
|
int pos= fPosition;
|
||||||
if (matchAccessSpecifier) {
|
if (looksLikeTypeInheritanceDecl()) {
|
||||||
return matchAccessSpecifierAlignment();
|
fIndent = fPrefs.prefContinuationIndent;
|
||||||
|
return fPosition;
|
||||||
|
}
|
||||||
|
fPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextToken();
|
nextToken();
|
||||||
// Skip access specifiers
|
// Skip access specifiers
|
||||||
while (fToken == Symbols.TokenCOLON && isAccessSpecifier()) {
|
while (fToken == Symbols.TokenCOLON && isAccessSpecifier()) {
|
||||||
|
@ -955,21 +1019,21 @@ public final class CIndenter {
|
||||||
switch (fToken) {
|
switch (fToken) {
|
||||||
case Symbols.TokenGREATERTHAN:
|
case Symbols.TokenGREATERTHAN:
|
||||||
case Symbols.TokenRBRACE:
|
case Symbols.TokenRBRACE:
|
||||||
// skip the block and fall through
|
// Skip the block and fall through.
|
||||||
// if we can't complete the scope, reset the scan position
|
// If we can't complete the scope, reset the scan position
|
||||||
int pos= fPosition;
|
int pos= fPosition;
|
||||||
if (!skipScope())
|
if (!skipScope())
|
||||||
fPosition= pos;
|
fPosition= pos;
|
||||||
return skipToStatementStart(danglingElse, false);
|
return skipToStatementStart(danglingElse, false);
|
||||||
|
|
||||||
case Symbols.TokenSEMICOLON:
|
case Symbols.TokenSEMICOLON:
|
||||||
// this is the 90% case: after a statement block
|
// This is the 90% case: after a statement block
|
||||||
// the end of the previous statement / block previous.end
|
// the end of the previous statement / block previous.end
|
||||||
// search to the end of the statement / block before the previous;
|
// search to the end of the statement / block before the previous;
|
||||||
// the token just after that is previous.start
|
// the token just after that is previous.start
|
||||||
return skipToStatementStart(danglingElse, false);
|
return skipToStatementStart(danglingElse, false);
|
||||||
|
|
||||||
// scope introduction: special treat who special is
|
// Scope introduction: special treat who special is
|
||||||
case Symbols.TokenLPAREN:
|
case Symbols.TokenLPAREN:
|
||||||
case Symbols.TokenLBRACE:
|
case Symbols.TokenLBRACE:
|
||||||
case Symbols.TokenLBRACKET:
|
case Symbols.TokenLBRACKET:
|
||||||
|
@ -977,7 +1041,7 @@ public final class CIndenter {
|
||||||
|
|
||||||
case Symbols.TokenEOF:
|
case Symbols.TokenEOF:
|
||||||
// trap when hitting start of document
|
// trap when hitting start of document
|
||||||
return CHeuristicScanner.NOT_FOUND;
|
return NOT_FOUND;
|
||||||
|
|
||||||
case Symbols.TokenEQUAL:
|
case Symbols.TokenEQUAL:
|
||||||
// indent assignments
|
// indent assignments
|
||||||
|
@ -992,7 +1056,7 @@ public final class CIndenter {
|
||||||
}
|
}
|
||||||
fPosition= pos;
|
fPosition= pos;
|
||||||
if (looksLikeTypeInheritanceDecl()) {
|
if (looksLikeTypeInheritanceDecl()) {
|
||||||
fIndent= fPrefs.prefBlockIndent;
|
fIndent= fPrefs.prefContinuationIndent;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
fPosition= pos;
|
fPosition= pos;
|
||||||
|
@ -1114,10 +1178,10 @@ public final class CIndenter {
|
||||||
if (fToken == Symbols.TokenSEMICOLON || fToken == Symbols.TokenEOF) {
|
if (fToken == Symbols.TokenSEMICOLON || fToken == Symbols.TokenEOF) {
|
||||||
return pos;
|
return pos;
|
||||||
} else {
|
} else {
|
||||||
return CHeuristicScanner.NOT_FOUND;
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return CHeuristicScanner.NOT_FOUND;
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1341,6 +1405,13 @@ public final class CIndenter {
|
||||||
return fPreviousPos;
|
return fPreviousPos;
|
||||||
|
|
||||||
case Symbols.TokenCOLON:
|
case Symbols.TokenCOLON:
|
||||||
|
switch (prevToken) {
|
||||||
|
case Symbols.TokenPRIVATE:
|
||||||
|
case Symbols.TokenPROTECTED:
|
||||||
|
case Symbols.TokenPUBLIC:
|
||||||
|
case Symbols.TokenVIRTUAL:
|
||||||
|
continue; // Don't stop at colon in a class declaration
|
||||||
|
}
|
||||||
int pos= fPreviousPos;
|
int pos= fPreviousPos;
|
||||||
if (!isConditional())
|
if (!isConditional())
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -1549,7 +1620,7 @@ public final class CIndenter {
|
||||||
int typeDeclPos= matchTypeDeclaration();
|
int typeDeclPos= matchTypeDeclaration();
|
||||||
fIndent= fPrefs.prefAccessSpecifierIndent;
|
fIndent= fPrefs.prefAccessSpecifierIndent;
|
||||||
fExtraSpaces = fPrefs.prefAccessSpecifierExtraSpaces;
|
fExtraSpaces = fPrefs.prefAccessSpecifierExtraSpaces;
|
||||||
if (typeDeclPos != CHeuristicScanner.NOT_FOUND) {
|
if (typeDeclPos != NOT_FOUND) {
|
||||||
return typeDeclPos;
|
return typeDeclPos;
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -1799,7 +1870,7 @@ public final class CIndenter {
|
||||||
fIndent = fPrefs.prefTypeIndent;
|
fIndent = fPrefs.prefTypeIndent;
|
||||||
} else {
|
} else {
|
||||||
int typeDeclPos = matchTypeDeclaration();
|
int typeDeclPos = matchTypeDeclaration();
|
||||||
if (typeDeclPos == CHeuristicScanner.NOT_FOUND) {
|
if (typeDeclPos == NOT_FOUND) {
|
||||||
fIndent= fPrefs.prefBlockIndent;
|
fIndent= fPrefs.prefBlockIndent;
|
||||||
} else {
|
} else {
|
||||||
fIndent= fPrefs.prefAccessSpecifierIndent + fPrefs.prefTypeIndent;
|
fIndent= fPrefs.prefAccessSpecifierIndent + fPrefs.prefTypeIndent;
|
||||||
|
@ -1845,7 +1916,7 @@ public final class CIndenter {
|
||||||
private int setFirstElementAlignment(int scopeIntroducerOffset, int bound) {
|
private int setFirstElementAlignment(int scopeIntroducerOffset, int bound) {
|
||||||
int firstPossible= scopeIntroducerOffset + 1; // align with the first position after the scope intro
|
int firstPossible= scopeIntroducerOffset + 1; // align with the first position after the scope intro
|
||||||
fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(firstPossible, bound);
|
fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(firstPossible, bound);
|
||||||
if (fAlign == CHeuristicScanner.NOT_FOUND) {
|
if (fAlign == NOT_FOUND) {
|
||||||
fAlign= firstPossible;
|
fAlign= firstPossible;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Reference in a new issue