diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index d955457d1c3..158faea8471 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -5650,6 +5650,58 @@ public class AST2Tests extends AST2BaseTest { } catch (ExpansionOverlapsBoundaryException e) {} } + + // #define IF if + // #define IF_P if ( + // #define IF_P_T if (1 + // #define SEMI_IF ; if + // #define IF_COND if (1) + // void test() { + public void testSyntax_Bug250251() throws Exception { + String code= getAboveComment(); + + IASTTranslationUnit tu= parseAndCheckBindings(code + "if (1) {};}"); + IASTFunctionDefinition f= getDeclaration(tu, 0); + IASTIfStatement x = getStatement(f, 0); + IToken syntax= x.getSyntax(); + checkToken(syntax, "if", 0); syntax= syntax.getNext(); + checkToken(syntax, "(", 3); syntax= syntax.getNext(); + checkToken(syntax, "1", 4); syntax= syntax.getNext(); + checkToken(syntax, ")", 5); syntax= syntax.getNext(); + checkToken(syntax, "{", 7); syntax= syntax.getNext(); + checkToken(syntax, "}", 8); syntax= syntax.getNext(); + assertNull(syntax); + + tu= parseAndCheckBindings(code + "if( 1) {}}"); + f= getDeclaration(tu, 0); x= getStatement(f, 0); + syntax= x.getSyntax(); + checkToken(syntax, "if", 0); syntax= syntax.getNext(); + checkToken(syntax, "(", 2); syntax= syntax.getNext(); + checkToken(syntax, "1", 5); syntax= syntax.getNext(); + checkToken(syntax, ")", 6); syntax= syntax.getNext(); + checkToken(syntax, "{", 8); syntax= syntax.getNext(); + checkToken(syntax, "}", 9); syntax= syntax.getNext(); + assertNull(syntax); + + tu= parseAndCheckBindings(code + "IF(1) {}}"); + f= getDeclaration(tu, 0); x= getStatement(f, 0); + syntax= x.getSyntax(); + checkToken(syntax, "IF", 0); syntax= syntax.getNext(); + checkToken(syntax, "(", 2); syntax= syntax.getNext(); + checkToken(syntax, "1", 3); syntax= syntax.getNext(); + checkToken(syntax, ")", 4); syntax= syntax.getNext(); + checkToken(syntax, "{", 6); syntax= syntax.getNext(); + checkToken(syntax, "}", 7); syntax= syntax.getNext(); + assertNull(syntax); + + tu= parseAndCheckBindings(code + "SEMI_IF (1) {}}"); + f= getDeclaration(tu, 0); x= getStatement(f, 1); + try { + syntax= x.getSyntax(); + fail(); + } catch (ExpansionOverlapsBoundaryException e) {} + } + private void checkToken(IToken token, String image, int offset) { assertEquals(image, token.getImage()); assertEquals(offset, token.getOffset()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java index cc86a5a3302..eaae0d04daa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java @@ -185,6 +185,19 @@ public interface IASTNode { */ public IToken getTrailingSyntax() throws ExpansionOverlapsBoundaryException, UnsupportedOperationException; + /** + * Returns the tokens that make up this node. The tokens are obtained from the lexer, + * no preprocessing is performed. + * The offsets of the tokens are relative to the file-offset of the beginning of this node. + *

For examples see {@link #getLeadingSyntax()}. + * @return a chain of tokens or null, if there are none. + * @throws ExpansionOverlapsBoundaryException if one of the boundaries of the node is + * overlapped by a macro-expansion. + * @throws UnsupportedOperationException if invoked on preprocessor nodes, or nodes that are not + * part of a translation unit. + * @since 5.1 + */ + public IToken getSyntax() throws ExpansionOverlapsBoundaryException; /** * Returns true if this node is frozen, false otherwise. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java index 18baaf6b0eb..fe7a16cdeea 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java @@ -222,6 +222,10 @@ public abstract class ASTNode implements IASTNode { return false; } + public IToken getSyntax() throws ExpansionOverlapsBoundaryException { + return getSyntax(offset, offset+length, 0); + } + public IToken getLeadingSyntax() throws ExpansionOverlapsBoundaryException { int left= getBoundary(-1); return getSyntax(left, offset, -1); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java index 7cdd2adddfe..37282bb2748 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java @@ -84,6 +84,10 @@ public class ASTLiteralNode implements IASTNode { public void setPropertyInParent(ASTNodeProperty property) { } + public IToken getSyntax() { + throw new UnsupportedOperationException(); + } + public IToken getLeadingSyntax() { throw new UnsupportedOperationException(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java index e611b5c74ec..799c85f28aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java @@ -195,6 +195,11 @@ public class PDOMASTAdapter { return this; } + public IToken getSyntax() throws ExpansionOverlapsBoundaryException, + UnsupportedOperationException { + return fDelegate.getSyntax(); + } + public IToken getLeadingSyntax() throws ExpansionOverlapsBoundaryException, UnsupportedOperationException { return fDelegate.getLeadingSyntax();