/******************************************************************************* * Copyright (c) 2009 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.util.BitSet; import junit.framework.TestSuite; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarationListOwner; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.core.parser.ParserLanguage; /** * Testcases for inactive code in ast. */ public class ASTInactiveCodeTests extends AST2BaseTest { public static TestSuite suite() { return suite(ASTInactiveCodeTests.class); } public ASTInactiveCodeTests() { super(); } public ASTInactiveCodeTests(String name) { super(name); } @Override protected void configureScanner(IScanner scanner) { super.configureScanner(scanner); scanner.setProcessInactiveCode(true); } // #if % // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; public void testIfBranches() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.C, i); } for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i); } } private void testBranches(String codeTmpl, ParserLanguage lang, int bits) throws Exception { testBranches(codeTmpl, lang, bits, 0); } private void testBranches(String codeTmpl, ParserLanguage lang, int bits, int level) throws Exception { BitSet bs= convert(bits); char[] chars= codeTmpl.toCharArray(); int pos= codeTmpl.indexOf('%', 0); int i= 0; while (pos >= 0) { chars[pos]= bs.get(i++) ? '1' : '0'; pos= codeTmpl.indexOf('%', pos+1); } IASTDeclarationListOwner tu= parse(new String(chars), lang); while (level-- > 0) { final IASTDeclaration decl = tu.getDeclarations(true)[0]; if (decl instanceof IASTSimpleDeclaration) { tu= (IASTDeclarationListOwner) ((IASTSimpleDeclaration) decl).getDeclSpecifier(); } else { tu= (IASTDeclarationListOwner) decl; } } IASTDeclaration[] decl= tu.getDeclarations(true); assertEquals(8, decl.length); assertEquals(bs.get(0), decl[0].isActive()); assertEquals(!bs.get(0) && bs.get(1), decl[1].isActive()); assertEquals(!bs.get(0) && bs.get(1) && bs.get(2), decl[2].isActive()); assertEquals(!bs.get(0) && bs.get(1) && !bs.get(2) && bs.get(3), decl[3].isActive()); assertEquals(!bs.get(0) && bs.get(1) && !bs.get(2) && !bs.get(3), decl[4].isActive()); assertEquals(!bs.get(0) && bs.get(1), decl[5].isActive()); assertEquals(!bs.get(0) && !bs.get(1), decl[6].isActive()); assertEquals(true, decl[7].isActive()); } private BitSet convert(int bits) { BitSet result= new BitSet(32); for (int i = 0; i < 32; i++) { if ((bits & (1 << i)) != 0) { result.set(i); } } return result; } // #define A1 // #ifdef A% // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; public void testIfdefBranches() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.C, i); } for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i); } } // #define A0 // #ifndef A% // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; public void testIfndefBranches() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.C, i); } for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i); } } // struct S { // #if % // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; // }; public void testStructs() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.C, i, 1); } for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i, 1); } } // extern "C" { // #if % // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; // }; public void testExternC() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i, 1); } } // namespace ns { // #if % // int a0; // #elif % // int a1; // #if % // int a2; // #elif % // int a3; // #else // int a4; // #endif // int a5; // #else // int a6; // #endif // int a7; // } public void testNamespace() throws Exception { String codeTmpl= getAboveComment(); for (int i= 0; i < (1<<4); i++) { testBranches(codeTmpl, ParserLanguage.CPP, i, 1); } } // typedef int TInt; // const int value= 12; // #if 0 // int f(TInt); // int g(value); // #endif public void testAmbiguity() throws Exception { String code= getAboveComment(); IASTTranslationUnit tu= parseAndCheckBindings(code, ParserLanguage.CPP); IASTDeclaration[] decls = tu.getDeclarations(true); IASTSimpleDeclaration decl= (IASTSimpleDeclaration) decls[2]; assertTrue(decl.getDeclarators()[0] instanceof IASTFunctionDeclarator); decl= (IASTSimpleDeclaration) decls[3]; assertFalse(decl.getDeclarators()[0] instanceof IASTFunctionDeclarator); } // int a; // 1 // #if 0 // int a; // 2 // #if 0 // int a; // 3 // #endif // int b; // 1 // #endif // int b; // 2 public void testDuplicateDefinition() throws Exception { String code= getAboveComment(); BindingAssertionHelper bh= new BindingAssertionHelper(code, false); bh.assertNonProblem("a; // 1", 1); bh.assertNonProblem("a; // 2", 1); bh.assertNonProblem("a; // 3", 1); bh.assertNonProblem("b; // 1", 1); bh.assertNonProblem("b; // 2", 1); bh= new BindingAssertionHelper(code, true); bh.assertNonProblem("a; // 1", 1); bh.assertNonProblem("a; // 2", 1); bh.assertNonProblem("a; // 3", 1); bh.assertNonProblem("b; // 1", 1); bh.assertNonProblem("b; // 2", 1); parseAndCheckBindings(code, ParserLanguage.C); parseAndCheckBindings(code, ParserLanguage.CPP); } // struct S { // #if 0 // int a; // }; // #else // int b; // }; // #endif public void testInactiveClosingBrace() throws Exception { String code= getAboveComment(); BindingAssertionHelper bh= new BindingAssertionHelper(code, false); IField a= bh.assertNonProblem("a;", 1); IField b= bh.assertNonProblem("b;", 1); assertSame(a.getOwner(), b.getOwner()); bh= new BindingAssertionHelper(code, true); a= bh.assertNonProblem("a;", 1); b= bh.assertNonProblem("b;", 1); assertSame(a.getOwner(), b.getOwner()); } // struct S // #if 1 // { // int a; // #else // int b; // #endif // int c; // #if 0 // int d; // #endif // }; public void testOpenBraceInActiveBranch() throws Exception { String code= getAboveComment(); BindingAssertionHelper bh= new BindingAssertionHelper(code, false); IField a= bh.assertNonProblem("a;", 1); bh.assertNoName("b;", 1); IField c= bh.assertNonProblem("c;", 1); IField d= bh.assertNonProblem("d;", 1); assertSame(a.getOwner(), c.getOwner()); assertSame(a.getOwner(), d.getOwner()); bh= new BindingAssertionHelper(code, true); a= bh.assertNonProblem("a;", 1); bh.assertNoName("b;", 1); c= bh.assertNonProblem("c;", 1); d= bh.assertNonProblem("d;", 1); assertSame(a.getOwner(), c.getOwner()); assertSame(a.getOwner(), d.getOwner()); } // #if 0 // struct S { // #if 1 // int a; // #else // int b; // #endif // #elif 0 // int c; // #endif // int d; public void testOpenBraceInInactiveBranch() throws Exception { String code= getAboveComment(); BindingAssertionHelper bh= new BindingAssertionHelper(code, false); IField a= bh.assertNonProblem("a;", 1); IField b= bh.assertNonProblem("b;", 1); IVariable c= bh.assertNonProblem("c;", 1); // part of a different non-nested branch IVariable d= bh.assertNonProblem("d;", 1); assertSame(a.getOwner(), b.getOwner()); assertNull(c.getOwner()); assertNull(d.getOwner()); bh= new BindingAssertionHelper(code, true); a= bh.assertNonProblem("a;", 1); b= bh.assertNonProblem("b;", 1); c= bh.assertNonProblem("c;", 1); // part of a different non-nested branch d= bh.assertNonProblem("d;", 1); assertSame(a.getOwner(), b.getOwner()); assertNull(c.getOwner()); assertNull(d.getOwner()); } // #if 0 // void f() { // #if 1 // int a; // #elif 0 // int b; // #endif // } // #endif public void testUnexpectedBranchesInInactiveCode() throws Exception { String code= getAboveComment(); BindingAssertionHelper bh= new BindingAssertionHelper(code, false); IFunction f= bh.assertNonProblem("f()", 1); bh.assertNoName("a;", 1); bh.assertNoName("b;", 1); bh= new BindingAssertionHelper(code, true); f= bh.assertNonProblem("f()", 1); bh.assertNoName("a;", 1); bh.assertNoName("b;", 1); } }