/*******************************************************************************
* Copyright (c) 2008, 2013 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
import java.io.IOException;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.NullLogService;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ParserMode;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser;
public class ASTNodeSelectorTest extends AST2TestBase {
static public TestSuite suite() {
return suite(ASTNodeSelectorTest.class);
}
protected String fCode;
protected IASTTranslationUnit fTu;
protected IASTNodeSelector fSelector;
public ASTNodeSelectorTest() {
}
public ASTNodeSelectorTest(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
createTranslationUnit();
}
protected void createTranslationUnit() throws IOException {
fCode= getContents(1)[0].toString();
FileContent codeReader = FileContent.create("<test-code>", fCode.toCharArray());
ScannerInfo scannerInfo = new ScannerInfo();
IScanner scanner= AST2TestBase.createScanner(codeReader, ParserLanguage.CPP, ParserMode.COMPLETE_PARSE, scannerInfo);
GNUCPPSourceParser parser= new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, new NullLogService(), new GPPParserExtensionConfiguration());
fTu= parser.parse();
fSelector= fTu.getNodeSelector(null);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
private void testContainedName(int from, int to, String sig) {
IASTName name= fSelector.findFirstContainedName(from, to-from);
verify(sig, name);
}
private void verify(String sig, IASTNode node) {
if (sig == null) {
assertNull("unexpexted selection: " + (node == null ? "" : node.getRawSignature()), node);
}
else {
assertNotNull("unable to select " + sig, node);
if (node instanceof IASTName) {
assertEquals(sig, ((IASTName) node).toString());
}
else {
assertEquals(sig, node.getRawSignature());
}
}
}
private void testContainedNode(int from, int to, String sig) {
IASTNode node= fSelector.findFirstContainedNode(from, to-from);
verify(sig, node);
}
private void testName(int from, int to, String sig) {
IASTName name= fSelector.findName(from, to-from);
verify(sig, name);
}
private void testNode(int from, int to, String sig) {
IASTNode node= fSelector.findNode(from, to-from);
verify(sig, node);
}
private void testEnclosingName(int from, int to, String sig) {
IASTName name= fSelector.findEnclosingName(from, to-from);
verify(sig, name);
}
private void testEnclosingNode(int from, int to, String sig) {
IASTNode node= fSelector.findEnclosingNode(from, to-from);
verify(sig, node);
}
private void testExpansion(int from, int to, String sig) {
IASTPreprocessorMacroExpansion exp= fSelector.findEnclosingMacroExpansion(from, to-from);
verify(sig, exp);
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #include <test>
// int a;
public void testInclusion() {
int include_start= fCode.indexOf("#include");
int name_start= fCode.indexOf("test");
int include_end= fCode.indexOf(">") + 1;
testContainedName(include_start-1, include_end+1, "test");
testContainedName(name_start, include_end, "test");
testContainedName(include_start+1, name_start+1, null);
testContainedName(name_start+1, name_start+7, null);
testContainedNode(include_start-1, include_end+1, "#include <test>");
testContainedNode(name_start, include_end, "test");
testContainedNode(include_start+1, name_start+1, null);
testContainedNode(name_start+1, name_start+7, null);
testEnclosingName(name_start, name_start+4, "test");
testEnclosingName(name_start, name_start, "test");
testEnclosingName(name_start+4, name_start+4, "test");
testEnclosingName(name_start-1, name_start+1, null);
testEnclosingName(name_start+4, name_start+5, null);
testEnclosingNode(name_start, name_start+4, "test");
testEnclosingNode(name_start, name_start, "test");
testEnclosingNode(name_start+4, name_start+4, "test");
testEnclosingNode(name_start-1, name_start+1, "#include <test>");
testEnclosingNode(name_start+4-1, name_start+4+1, "#include <test>");
testExpansion(name_start, name_start+4, null);
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define EMPTY
// #define TEST_H "test.h"
// void func() {
// #include EMPTY TEST_H
// }
public void testInclusionWithExpansions() {
int inclusion_start= fCode.indexOf("#include");
int empty_start= fCode.indexOf("EMPTY", inclusion_start);
int testh_start= fCode.indexOf("TEST_H", empty_start);
int file_end= fCode.length();
testContainedName(inclusion_start-1, file_end-1, "EMPTY");
testContainedName(testh_start, file_end, "TEST_H");
testContainedName(testh_start+1, file_end, null);
testContainedName(testh_start, testh_start+5, null);
testContainedNode(inclusion_start-1, file_end+1, "#include EMPTY TEST_H");
testContainedNode(testh_start, file_end, "TEST_H");
testContainedNode(testh_start+1, file_end, null);
testContainedNode(testh_start, testh_start+5, null);
testName(empty_start, empty_start+5, "EMPTY");
testName(empty_start-1, empty_start+5, null);
testName(empty_start+1, empty_start+5, null);
testName(empty_start, empty_start+4, null);
testName(empty_start, empty_start+6, null);
testNode(empty_start, empty_start+5, "EMPTY");
testNode(empty_start-1, empty_start+5, null);
testNode(empty_start+1, empty_start+5, null);
testNode(empty_start, empty_start+4, null);
testNode(empty_start, empty_start+6, null);
testEnclosingName(empty_start, empty_start+5, "EMPTY");
testEnclosingName(empty_start, empty_start, "EMPTY");
testEnclosingName(empty_start+5, empty_start+5, "EMPTY");
testEnclosingName(empty_start-1, empty_start, null);
testEnclosingName(empty_start+5, empty_start+6, "test.h");
testEnclosingName(testh_start, testh_start+6, "TEST_H");
testEnclosingName(testh_start, testh_start, "TEST_H");
testEnclosingName(testh_start+6, testh_start+6, "TEST_H");
testEnclosingName(testh_start-1, testh_start+1, "test.h");
testEnclosingName(testh_start+5, testh_start+7, null);
testEnclosingNode(empty_start, empty_start+5, "EMPTY");
testEnclosingNode(empty_start, empty_start, "EMPTY");
testEnclosingNode(empty_start+5, empty_start+5, "EMPTY");
testEnclosingNode(empty_start-1, empty_start, "#include EMPTY TEST_H");
testEnclosingNode(empty_start+5, empty_start+6, "test.h");
testEnclosingNode(testh_start, testh_start+6, "TEST_H");
testEnclosingNode(testh_start, testh_start, "TEST_H");
testEnclosingNode(testh_start+6, testh_start+6, "TEST_H");
testEnclosingNode(testh_start-1, testh_start+1, "test.h");
testEnclosingNode(testh_start+6-1, testh_start+6+1, "{\n #include EMPTY TEST_H\n }");
testExpansion(empty_start, empty_start+5, "EMPTY");
testExpansion(empty_start, empty_start, "EMPTY");
testExpansion(empty_start+5, empty_start+5, "EMPTY");
testExpansion(empty_start-1, empty_start, null);
testExpansion(empty_start+5, empty_start+6, null);
testExpansion(testh_start, testh_start+6, "TEST_H");
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define xx 1
// #if xx == 2
// #elif xx == 1
// #endif
public void testMacroInConditionalExpression() {
int x1= fCode.indexOf("xx");
int x2= fCode.indexOf("xx", x1+1);
int x3= fCode.indexOf("xx", x2+1);
testContainedName(x1, x1+2, "xx");
testContainedName(x2-1, x2+2, "xx");
testContainedName(x3, x3+3, "xx");
testContainedName(x1, x1+1, null);
testContainedName(x2+1, x2+2, null);
testContainedName(x3+1, x3+1, null);
testName(x1, x1+2, "xx");
testName(x2, x2+2, "xx");
testName(x3, x3+2, "xx");
testName(x1+1, x1+2, null);
testName(x2-1, x2+2, null);
testName(x3, x3+3, null);
testName(x3, x3+1, null);
testEnclosingName(x1, x1+2, "xx");
testEnclosingName(x2+2, x2+2, "xx");
testEnclosingName(x3, x3, "xx");
testEnclosingName(x1-1, x1+2, null);
testEnclosingName(x2+2, x2+3, null);
testEnclosingName(x3-1, x3-1, null);
testExpansion(x1, x1+2, null);
testExpansion(x2+2, x2+2, "xx");
testExpansion(x3, x3, "xx");
testExpansion(x2+2, x2+3, null);
testExpansion(x3-1, x3-1, null);
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define xx 1
// #if !defined(xx)
// #elif defined(xx) == 1
// #endif
public void testMacroInDefinedExpression() {
int x1= fCode.indexOf("xx");
int x2= fCode.indexOf("xx", x1+1);
int x3= fCode.indexOf("xx", x2+1);
testContainedName(x1, x1+2, "xx");
testContainedName(x2-1, x2+2, "xx");
testContainedName(x3, x3+3, "xx");
testContainedName(x1, x1+1, null);
testContainedName(x2+1, x2+2, null);
testContainedName(x3+1, x3+1, null);
testName(x1, x1+2, "xx");
testName(x2, x2+2, "xx");
testName(x3, x3+2, "xx");
testName(x1+1, x1+2, null);
testName(x2-1, x2+2, null);
testName(x3, x3+3, null);
testName(x3, x3+1, null);
testEnclosingName(x1, x1+2, "xx");
testEnclosingName(x2+2, x2+2, "xx");
testEnclosingName(x3, x3, "xx");
testEnclosingName(x1-1, x1+2, null);
testEnclosingName(x2+2, x2+3, null);
testEnclosingName(x3-1, x3-1, null);
testExpansion(x1, x1+2, null);
testExpansion(x2+2, x2+2, null);
testExpansion(x3, x3, null);
testExpansion(x2+2, x2+3, null);
testExpansion(x3-1, x3-1, null);
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define xx 1
// #ifndef xx
// #endif
// #ifdef xx
// #endif
// #undef xx
public void testMacroInConditional() {
int x1= fCode.indexOf("xx");
x1= fCode.indexOf("xx", x1+1);
int x2= fCode.indexOf("xx", x1+1);
int x3= fCode.indexOf("xx", x2+1);
testContainedName(x1, x1+2, "xx");
testContainedName(x2-1, x2+2, "xx");
testContainedName(x3, x3+3, "xx");
testContainedName(x1, x1+1, null);
testContainedName(x2+1, x2+2, null);
testContainedName(x3+1, x3+1, null);
testName(x1, x1+2, "xx");
testName(x2, x2+2, "xx");
testName(x3, x3+2, "xx");
testName(x1+1, x1+2, null);
testName(x2-1, x2+2, null);
testName(x3, x3+3, null);
testName(x3, x3+1, null);
testEnclosingName(x1, x1+2, "xx");
testEnclosingName(x2+2, x2+2, "xx");
testEnclosingName(x3, x3, "xx");
testEnclosingName(x1-1, x1+2, null);
testEnclosingName(x2+2, x2+3, null);
testEnclosingName(x3-1, x3-1, null);
testExpansion(x1, x1+2, null);
testExpansion(x2+2, x2+2, null);
testExpansion(x3, x3, null);
testExpansion(x2+2, x2+3, null);
testExpansion(x3-1, x3-1, null);
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define IMPLICIT 1
// #define EXPLICIT IMPLICIT
// int a= EXPLICIT;
public void testUnreachableImplicitMacro() {
int x1= fCode.indexOf("EXPLICIT;");
testContainedName(x1, fCode.length(), "EXPLICIT");
testName(x1, x1+8, "EXPLICIT");
testEnclosingName(x1, x1, "EXPLICIT");
}
// #define shift_offsets
// int shift= shift_offsets;
//
// #define NESTED 1
// #define EXPLICIT(x) x
// int a= EXPLICIT(NESTED);
public void testReachableNestedMacro() {
int x1= fCode.indexOf("NESTED)");
testContainedName(x1, fCode.length(), "NESTED");
testName(x1, x1+6, "NESTED");
testEnclosingName(x1, x1, "NESTED");
}
// #define id(x,y) x y
// id(int a, =1);
// id(int b=, a);
public void testImageLocations() {
int a1= fCode.indexOf("a");
int a2= fCode.indexOf("a", a1+1);
int b1= fCode.indexOf("b");
testName(a1, a1+1, "a");
testContainedName(a1-1, a2+2, "a");
testEnclosingName(a1, a1, "a");
testEnclosingName(a1+1, a1+1, "a");
testName(a2, a2+1, "a");
testContainedName(a2-1, a2+2, "a");
testEnclosingName(a2, a2, "a");
testEnclosingName(a2+1, a2+1, "a");
testEnclosingNode(a1-1, a1+1, "id(int a, =1)");
testContainedNode(a1-8, a1+1, "id");
}
// namespace ns {int a;}
// int x= ns::a;
// #define M int b;
// M
// #define N() int c;
// N()
// #define O
// #define P()
// P()O
public void testOrdering() {
int x1= fCode.indexOf("ns::a");
int x2= x1 + "ns::a".length();
testContainedName(x1, x2, "ns");
testEnclosingName(x2-1, x2-1, "a");
testEnclosingName(x2, x2, "a");
x1= fCode.indexOf("M"); x1= fCode.indexOf("M", x1+1);
testNode(x1, x1+1, "M");
testEnclosingNode(x1, x1, "M");
testEnclosingNode(x1+1, x1+1, "M");
testContainedNode(x1-1, x1+2, "M");
x1= fCode.indexOf("N"); x1= fCode.indexOf("N", x1+1);
testNode(x1, x1+1, "N");
testEnclosingNode(x1, x1, "N");
testEnclosingNode(x1+1, x1+1, "N");
testContainedNode(x1-1, x1+2, "N");
x1= fCode.indexOf("O"); x1= fCode.indexOf("O", x1+1);
testNode(x1, x1+1, "O");
testEnclosingNode(x1, x1, "O");
testEnclosingNode(x1+1, x1+1, "O");
testContainedNode(x1-1, x1+2, "O");
}
// #define MACRO void m
// MACRO();
public void testEnclosingAMacro() {
int x1= fCode.indexOf("MACRO(");
int x2= x1 + "MACRO(".length();
testContainedName(x1, x2, "MACRO");
testEnclosingNode(x1, x2, "MACRO();");
}
}