mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Formatting of function-style macro expansions.
This commit is contained in:
parent
9959005ff7
commit
07ba8ca44b
3 changed files with 177 additions and 10 deletions
|
@ -74,6 +74,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
||||||
|
@ -92,6 +93,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer;
|
||||||
|
@ -175,6 +177,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
public boolean fSpaceBeforeOpeningParen;
|
public boolean fSpaceBeforeOpeningParen;
|
||||||
public int fContinuationIndentation= -1;
|
public int fContinuationIndentation= -1;
|
||||||
public int fTieBreakRule = Alignment.R_INNERMOST;
|
public int fTieBreakRule = Alignment.R_INNERMOST;
|
||||||
|
|
||||||
public ListAlignment(int mode) {
|
public ListAlignment(int mode) {
|
||||||
fMode= mode;
|
fMode= mode;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +211,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
private MultiStatus fStatus;
|
private MultiStatus fStatus;
|
||||||
private int fOpenAngleBrackets;
|
private int fOpenAngleBrackets;
|
||||||
|
|
||||||
|
|
||||||
public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, int offset, int length) {
|
public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, int offset, int length) {
|
||||||
localScanner = new Scanner() {
|
localScanner = new Scanner() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -219,7 +221,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
scribe = new Scribe(this, offset, length);
|
scribe = new Scribe(this, offset, length);
|
||||||
|
@ -240,7 +241,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
scribe.initializeScanner(compilationUnitSource);
|
scribe.initializeScanner(compilationUnitSource);
|
||||||
scribe.setSkipPositions(collectInactiveCodePositions(unit));
|
scribe.setSkipPositions(collectInactiveCodePositions(unit));
|
||||||
|
|
||||||
fStatus= new MultiStatus(CCorePlugin.PLUGIN_ID, 0, "Formatting problem(s) in '"+unit.getFilePath()+"'", null); //$NON-NLS-1$ //$NON-NLS-2$
|
fStatus= new MultiStatus(CCorePlugin.PLUGIN_ID, 0,
|
||||||
|
"Formatting problem(s) in '" + unit.getFilePath() + "'", null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
try {
|
try {
|
||||||
unit.accept(this);
|
unit.accept(this);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -294,6 +296,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
scribe.lastNumberOfNewLines = 1;
|
scribe.lastNumberOfNewLines = 1;
|
||||||
scribe.startNewLine();
|
scribe.startNewLine();
|
||||||
final int indentLevel= scribe.indentationLevel;
|
final int indentLevel= scribe.indentationLevel;
|
||||||
|
IASTPreprocessorMacroExpansion[] macroExpansions = tu.getMacroExpansions();
|
||||||
|
int m = 0;
|
||||||
IASTDeclaration[] decls= tu.getDeclarations();
|
IASTDeclaration[] decls= tu.getDeclarations();
|
||||||
for (int i = 0; i < decls.length; i++) {
|
for (int i = 0; i < decls.length; i++) {
|
||||||
IASTDeclaration declaration = decls[i];
|
IASTDeclaration declaration = decls[i];
|
||||||
|
@ -301,14 +305,36 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
int pos = scribe.scanner.getCurrentPosition();
|
||||||
|
IASTFileLocation declarationLocation = declaration.getFileLocation();
|
||||||
|
int declarartionOffset = declarationLocation.getNodeOffset();
|
||||||
|
int declarationEndOffset = declarartionOffset + declarationLocation.getNodeLength();
|
||||||
|
for (; m < macroExpansions.length; m++) {
|
||||||
|
IASTPreprocessorMacroExpansion macroExpansion = macroExpansions[m];
|
||||||
|
IASTFileLocation macroLocation = macroExpansion.getFileLocation();
|
||||||
|
int macroOffset = macroLocation.getNodeOffset();
|
||||||
|
if (macroOffset > declarartionOffset) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int macroEndOffset = macroOffset + macroLocation.getNodeLength();
|
||||||
|
if (isFunctionStyleMacroExpansion(macroExpansion) && macroOffset >= pos &&
|
||||||
|
(macroEndOffset <= declarartionOffset || macroEndOffset >= declarationEndOffset)) {
|
||||||
|
// The function-style macro expansion either doesn't overlap with
|
||||||
|
// the following declaration, or the declaration is completely covered by
|
||||||
|
// the macro expansion. In both cases formatting is driven by the text of
|
||||||
|
// parameters of the macro, not by the expanded code.
|
||||||
|
formatFunctionStyleMacroExpansion(macroExpansion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
declaration.accept(this);
|
declaration.accept(this);
|
||||||
scribe.startNewLine();
|
scribe.startNewLine();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// report, but continue
|
// Report, but continue
|
||||||
reportFormattingProblem(e);
|
reportFormattingProblem(e);
|
||||||
if (i < decls.length - 1) {
|
if (i < decls.length - 1) {
|
||||||
exitAlignments();
|
exitAlignments();
|
||||||
skipToNode(decls[i+1]);
|
skipToNode(decls[i + 1]);
|
||||||
while (scribe.indentationLevel < indentLevel) {
|
while (scribe.indentationLevel < indentLevel) {
|
||||||
scribe.indent();
|
scribe.indent();
|
||||||
}
|
}
|
||||||
|
@ -321,6 +347,107 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
scribe.printEndOfTranslationUnit();
|
scribe.printEndOfTranslationUnit();
|
||||||
return PROCESS_SKIP;
|
return PROCESS_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isFunctionStyleMacroExpansion(IASTPreprocessorMacroExpansion macroExpansion) {
|
||||||
|
IASTName name = macroExpansion.getMacroReference();
|
||||||
|
IMacroBinding binding = (IMacroBinding) name.resolveBinding();
|
||||||
|
return binding.isFunctionStyle() && binding.getParameterList().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void formatFunctionStyleMacroExpansion(IASTPreprocessorMacroExpansion macroExpansion) {
|
||||||
|
IASTName name = macroExpansion.getMacroReference();
|
||||||
|
IASTFileLocation fileLocation= name.getFileLocation();
|
||||||
|
if (fileLocation != null) {
|
||||||
|
scribe.printRaw(fileLocation.getNodeOffset(), fileLocation.getNodeLength());
|
||||||
|
}
|
||||||
|
fileLocation = macroExpansion.getFileLocation();
|
||||||
|
scribe.printNextToken(Token.tLPAREN);
|
||||||
|
IMacroBinding binding = (IMacroBinding) name.resolveBinding();
|
||||||
|
if (preferences.insert_space_after_opening_paren_in_method_invocation) {
|
||||||
|
scribe.space();
|
||||||
|
}
|
||||||
|
final int continuationIndentation = preferences.continuation_indentation;
|
||||||
|
Alignment listAlignment = scribe.createAlignment(
|
||||||
|
"macroArguments", //$NON-NLS-1$
|
||||||
|
preferences.alignment_for_arguments_in_method_invocation,
|
||||||
|
Alignment.R_OUTERMOST,
|
||||||
|
binding.getParameterList().length,
|
||||||
|
scribe.scanner.getCurrentPosition(),
|
||||||
|
continuationIndentation,
|
||||||
|
false);
|
||||||
|
scribe.enterAlignment(listAlignment);
|
||||||
|
boolean ok = false;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
int fragment = 0;
|
||||||
|
scribe.alignFragment(listAlignment, fragment);
|
||||||
|
int parenLevel= 0;
|
||||||
|
boolean done = false;
|
||||||
|
while (!done) {
|
||||||
|
boolean hasWhitespace= scribe.printComment();
|
||||||
|
int token = peekNextToken();
|
||||||
|
switch (token) {
|
||||||
|
case Token.tLPAREN:
|
||||||
|
++parenLevel;
|
||||||
|
scribe.printNextToken(token, hasWhitespace);
|
||||||
|
break;
|
||||||
|
case Token.tRPAREN:
|
||||||
|
if (parenLevel > 0) {
|
||||||
|
--parenLevel;
|
||||||
|
scribe.printNextToken(token, hasWhitespace);
|
||||||
|
} else {
|
||||||
|
if (preferences.insert_space_before_closing_paren_in_method_invocation) {
|
||||||
|
scribe.space();
|
||||||
|
}
|
||||||
|
scribe.printNextToken(token);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Token.tCOMMA:
|
||||||
|
if (parenLevel == 0 && preferences.insert_space_before_comma_in_method_invocation_arguments) {
|
||||||
|
scribe.space();
|
||||||
|
}
|
||||||
|
scribe.printNextToken(token);
|
||||||
|
if (parenLevel == 0) {
|
||||||
|
if (preferences.insert_space_after_comma_in_method_invocation_arguments) {
|
||||||
|
scribe.space();
|
||||||
|
}
|
||||||
|
scribe.printComment();
|
||||||
|
++fragment;
|
||||||
|
if (fragment < listAlignment.fragmentCount) {
|
||||||
|
scribe.alignFragment(listAlignment, fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Token.tSTRING:
|
||||||
|
case Token.tLSTRING:
|
||||||
|
case Token.tRSTRING:
|
||||||
|
boolean needSpace= hasWhitespace;
|
||||||
|
while (true) {
|
||||||
|
scribe.printNextToken(token, needSpace);
|
||||||
|
if (peekNextToken() != token) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scribe.printCommentPreservingNewLines();
|
||||||
|
needSpace= true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scribe.printNextToken(token, hasWhitespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int token = peekNextToken();
|
||||||
|
if (token == Token.tSEMI) {
|
||||||
|
scribe.printNextToken(token);
|
||||||
|
scribe.startNewLine();
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
} catch (AlignmentException e) {
|
||||||
|
scribe.redoAlignment(e);
|
||||||
|
}
|
||||||
|
} while (!ok);
|
||||||
|
scribe.exitAlignment(listAlignment, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int visit(IASTDeclaration node) {
|
public int visit(IASTDeclaration node) {
|
||||||
|
@ -861,7 +988,10 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
}
|
}
|
||||||
scribe.space();
|
scribe.space();
|
||||||
node.getName().accept(this);
|
node.getName().accept(this);
|
||||||
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon);
|
int token = peekNextToken();
|
||||||
|
if (token == Token.tSEMI) {
|
||||||
|
scribe.printNextToken(token, preferences.insert_space_before_semicolon);
|
||||||
|
}
|
||||||
return PROCESS_SKIP;
|
return PROCESS_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3626,8 +3756,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
positions.add(new Position(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));
|
positions.add(new Position(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));
|
||||||
}
|
}
|
||||||
inInactiveCode = wasInInactiveCode;
|
inInactiveCode = wasInInactiveCode;
|
||||||
}
|
} catch (EmptyStackException e) {
|
||||||
catch( EmptyStackException e) {}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inInactiveCode) {
|
if (inInactiveCode) {
|
||||||
|
|
|
@ -1301,7 +1301,7 @@ public class Scribe {
|
||||||
pendingSpace= false;
|
pendingSpace= false;
|
||||||
needSpace= true;
|
needSpace= true;
|
||||||
throw new AbortFormatting(
|
throw new AbortFormatting(
|
||||||
"[" + (line+1) + "/" + column + "] unexpected token type, expecting:" + expectedTokenType + ", actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
"[" + (line + 1) + "/" + column + "] unexpected token type, expecting:" + expectedTokenType + ", actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||||
}
|
}
|
||||||
print(currentToken.getLength(), considerSpaceIfAny);
|
print(currentToken.getLength(), considerSpaceIfAny);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1333,7 +1333,7 @@ public class Scribe {
|
||||||
expectations.append(expectedTokenTypes[i]);
|
expectations.append(expectedTokenTypes[i]);
|
||||||
}
|
}
|
||||||
throw new AbortFormatting(
|
throw new AbortFormatting(
|
||||||
"[" + (line+1) + "/" + column + "] unexpected token type, expecting:[" + expectations.toString() + "], actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
"[" + (line + 1) + "/" + column + "] unexpected token type, expecting:[" + expectations.toString() + "], actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
|
||||||
}
|
}
|
||||||
print(currentToken.getLength(), considerSpaceIfAny);
|
print(currentToken.getLength(), considerSpaceIfAny);
|
||||||
}
|
}
|
||||||
|
|
|
@ -941,6 +941,43 @@ public class CodeFormatterTest extends BaseUITestCase {
|
||||||
assertFormatterResult();
|
assertFormatterResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define MY_MACRO(a, b, c)
|
||||||
|
//
|
||||||
|
//MY_MACRO(abcdefghijklmnopqrstuvwxyz,25,"very very very very very very very very very very long text");
|
||||||
|
|
||||||
|
//#define MY_MACRO(a, b, c)
|
||||||
|
//
|
||||||
|
//MY_MACRO(abcdefghijklmnopqrstuvwxyz, 25,
|
||||||
|
// "very very very very very very very very very very long text");
|
||||||
|
public void testFunctionStyleMacro_1() throws Exception {
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
|
||||||
|
assertFormatterResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define MY_MACRO(a, b, c) \
|
||||||
|
//int a = b; \
|
||||||
|
//const char s[] = c
|
||||||
|
//
|
||||||
|
//MY_MACRO(abcdefghijklmnopqrstuvwxyz,(25 + 3),"very very very very very very very very very very long text");
|
||||||
|
|
||||||
|
//#define MY_MACRO(a, b, c) \
|
||||||
|
//int a = b; \
|
||||||
|
//const char s[] = c
|
||||||
|
//
|
||||||
|
//MY_MACRO( abcdefghijklmnopqrstuvwxyz,
|
||||||
|
// (25 + 3),
|
||||||
|
// "very very very very very very very very very very long text" );
|
||||||
|
public void testFunctionStyleMacro_2() throws Exception {
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION,
|
||||||
|
Integer.toString(Alignment.M_NEXT_PER_LINE_SPLIT | Alignment.M_INDENT_ON_COLUMN));
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_METHOD_INVOCATION,
|
||||||
|
CCorePlugin.INSERT);
|
||||||
|
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_METHOD_INVOCATION,
|
||||||
|
CCorePlugin.INSERT);
|
||||||
|
assertFormatterResult();
|
||||||
|
}
|
||||||
|
|
||||||
//void foo() {
|
//void foo() {
|
||||||
//for(int i=0;i<50;++i){}
|
//for(int i=0;i<50;++i){}
|
||||||
//}
|
//}
|
||||||
|
|
Loading…
Add table
Reference in a new issue