blob: 7a1d3870cbcb201dcf1c447affd4a9bbf04c6a88 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2013 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
import java.io.IOException;
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;
import junit.framework.TestSuite;
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();");
}
}