| /******************************************************************************* |
| * Copyright (c) 2004, 2016 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| * Markus Schorn (Wind River Systems) |
| * Andrew Ferguson (Symbian) |
| * Mike Kucera (IBM) |
| * Sergey Prigogin (Google) |
| * Nathan Ridge |
| *******************************************************************************/ |
| package org.eclipse.cdt.core.parser.tests.ast2; |
| |
| import static org.eclipse.cdt.core.parser.ParserLanguage.CPP; |
| |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; |
| import org.eclipse.cdt.core.dom.ast.ASTVisitor; |
| import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTCastExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; |
| import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclaration; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| import org.eclipse.cdt.core.dom.ast.IASTIdExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; |
| import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorNameOwner; |
| import org.eclipse.cdt.core.dom.ast.IASTImplicitName; |
| import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; |
| import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; |
| 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.IASTSimpleDeclaration; |
| import org.eclipse.cdt.core.dom.ast.IASTStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
| import org.eclipse.cdt.core.dom.ast.IASTTypeId; |
| import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; |
| import org.eclipse.cdt.core.dom.ast.IBinding; |
| import org.eclipse.cdt.core.dom.ast.ICompositeType; |
| import org.eclipse.cdt.core.dom.ast.IField; |
| import org.eclipse.cdt.core.dom.ast.IFunctionType; |
| import org.eclipse.cdt.core.dom.ast.IProblemBinding; |
| import org.eclipse.cdt.core.dom.ast.IType; |
| import org.eclipse.cdt.core.dom.ast.IValue; |
| import org.eclipse.cdt.core.dom.ast.IVariable; |
| import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; |
| import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.c.GCCParserExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.c.GCCScannerExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.c.ICParserExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration; |
| import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration; |
| import org.eclipse.cdt.core.parser.FileContent; |
| import org.eclipse.cdt.core.parser.IParserLogService; |
| import org.eclipse.cdt.core.parser.IScanner; |
| import org.eclipse.cdt.core.parser.IScannerInfo; |
| import org.eclipse.cdt.core.parser.IncludeFileContentProvider; |
| 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.core.parser.tests.ASTComparer; |
| import org.eclipse.cdt.core.testplugin.CTestPlugin; |
| import org.eclipse.cdt.core.testplugin.util.BaseTestCase; |
| import org.eclipse.cdt.core.testplugin.util.TestSourceReader; |
| import org.eclipse.cdt.internal.core.dom.parser.ASTNode; |
| import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CBasicType; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CPointerType; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CQualifierType; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; |
| import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; |
| import org.eclipse.cdt.internal.core.model.ASTStringUtil; |
| import org.eclipse.cdt.internal.core.parser.ParserException; |
| import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; |
| |
| import junit.framework.AssertionFailedError; |
| |
| /** |
| * @author aniefer |
| */ |
| public class AST2TestBase extends BaseTestCase { |
| public final static String TEST_CODE = "<testcode>"; |
| protected static final IParserLogService NULL_LOG = new NullLogService(); |
| protected static boolean sValidateCopy; |
| |
| protected static class CommonCTypes { |
| public static IType pointerToVoid = pointerTo(CBasicType.VOID); |
| public static IType pointerToConstVoid = pointerTo(constOf(CBasicType.VOID)); |
| public static IType pointerToConstInt = pointerTo(constOf(CBasicType.INT)); |
| public static IType pointerToVolatileInt = pointerTo(volatileOf(CBasicType.INT)); |
| public static IType pointerToConstVolatileInt = pointerTo(constVolatileOf(CBasicType.INT)); |
| |
| private static IType pointerTo(IType type) { |
| return new CPointerType(type, 0); |
| } |
| private static IType constOf(IType type) { |
| return new CQualifierType(type, true, false, false); |
| } |
| private static IType volatileOf(IType type) { |
| return new CQualifierType(type, false, true, false); |
| } |
| private static IType constVolatileOf(IType type) { |
| return new CQualifierType(type, true, true, false); |
| } |
| } |
| |
| protected static class CommonCPPTypes { |
| public static IType int_ = CPPBasicType.INT; |
| public static IType void_ = CPPBasicType.VOID; |
| public static IType constInt = constOf(int_); |
| public static IType pointerToInt = pointerTo(int_); |
| public static IType pointerToConstInt = pointerTo(constInt); |
| public static IType referenceToInt = referenceTo(int_); |
| public static IType referenceToConstInt = referenceTo(constInt); |
| public static IType rvalueReferenceToInt = rvalueReferenceTo(int_); |
| public static IType rvalueReferenceToConstInt = rvalueReferenceTo(constInt); |
| |
| private static IType pointerTo(IType type) { |
| return new CPPPointerType(type); |
| } |
| |
| private static IType constOf(IType type) { |
| return new CPPQualifierType(type, true, false); |
| } |
| |
| private static IType referenceTo(IType type) { |
| return new CPPReferenceType(type, false); |
| } |
| |
| private static IType rvalueReferenceTo(IType type) { |
| return new CPPReferenceType(type, true); |
| } |
| } |
| |
| private static final ScannerInfo GNU_SCANNER_INFO = new ScannerInfo(getGnuMap()); |
| private static final ScannerInfo SCANNER_INFO = new ScannerInfo(getStdMap()); |
| |
| private static Map<String, String> getGnuMap() { |
| Map<String, String> map= new HashMap<>(); |
| map.put("__GNUC__", Integer.toString(GCC_MAJOR_VERSION_FOR_TESTS)); |
| map.put("__GNUC_MINOR__", Integer.toString(GCC_MINOR_VERSION_FOR_TESTS)); |
| map.put("__SIZEOF_SHORT__", "2"); |
| map.put("__SIZEOF_INT__", "4"); |
| map.put("__SIZEOF_LONG__", "8"); |
| map.put("__SIZEOF_DOUBLE__", "8"); |
| map.put("__SIZEOF_POINTER__", "8"); |
| return map; |
| } |
| |
| private static Map<String, String> getStdMap() { |
| Map<String, String> map= new HashMap<>(); |
| map.put("__SIZEOF_SHORT__", "2"); |
| map.put("__SIZEOF_INT__", "4"); |
| map.put("__SIZEOF_LONG__", "8"); |
| map.put("__SIZEOF_DOUBLE__", "8"); |
| map.put("__SIZEOF_POINTER__", "8"); |
| return map; |
| } |
| |
| public AST2TestBase() { |
| super(); |
| } |
| |
| public AST2TestBase(String name) { |
| super(name); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| sValidateCopy= true; |
| super.setUp(); |
| } |
| |
| protected IASTTranslationUnit parse(String code, ParserLanguage lang) throws ParserException { |
| return parse(code, lang, false, true); |
| } |
| |
| protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions) throws ParserException { |
| return parse(code, lang, useGNUExtensions, true); |
| } |
| |
| protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions, |
| boolean expectNoProblems) throws ParserException { |
| return parse(code, lang, useGNUExtensions, expectNoProblems, Integer.MAX_VALUE); |
| } |
| |
| protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions, |
| boolean expectNoProblems, int limitTrivialInitializers) throws ParserException { |
| IScanner scanner = createScanner(FileContent.create(TEST_CODE, code.toCharArray()), lang, ParserMode.COMPLETE_PARSE, |
| createScannerInfo(useGNUExtensions)); |
| configureScanner(scanner); |
| AbstractGNUSourceCodeParser parser = null; |
| if (lang == ParserLanguage.CPP) { |
| ICPPParserExtensionConfiguration config = null; |
| if (useGNUExtensions) { |
| config = new GPPParserExtensionConfiguration(); |
| } else { |
| config = new ANSICPPParserExtensionConfiguration(); |
| } |
| parser = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config, null); |
| } else { |
| ICParserExtensionConfiguration config = null; |
| |
| if (useGNUExtensions) { |
| config = new GCCParserExtensionConfiguration(); |
| } else { |
| config = new ANSICParserExtensionConfiguration(); |
| } |
| |
| parser = new GNUCSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config, null); |
| } |
| parser.setMaximumTrivialExpressionsInAggregateInitializers(limitTrivialInitializers); |
| |
| IASTTranslationUnit tu = parser.parse(); |
| assertTrue(tu.isFrozen()); |
| if (sValidateCopy) |
| validateCopy(tu); |
| |
| if (parser.encounteredError() && expectNoProblems) |
| throw new ParserException("FAILURE"); //$NON-NLS-1$ |
| |
| if (lang == ParserLanguage.C && expectNoProblems) { |
| assertEquals(CVisitor.getProblems(tu).length, 0); |
| assertEquals(tu.getPreprocessorProblems().length, 0); |
| } else if (lang == ParserLanguage.CPP && expectNoProblems) { |
| assertEquals(CPPVisitor.getProblems(tu).length, 0); |
| assertEquals(0, tu.getPreprocessorProblems().length); |
| } |
| if (expectNoProblems) |
| assertEquals(0, tu.getPreprocessorProblems().length); |
| |
| return tu; |
| } |
| |
| public ScannerInfo createScannerInfo(boolean useGnu) { |
| if (useGnu) |
| return GNU_SCANNER_INFO; |
| return SCANNER_INFO; |
| } |
| |
| protected void configureScanner(IScanner scanner) { |
| } |
| |
| public static IScanner createScanner(FileContent codeReader, ParserLanguage lang, ParserMode mode, |
| IScannerInfo scannerInfo) { |
| IScannerExtensionConfiguration configuration = null; |
| if (lang == ParserLanguage.C) { |
| configuration= GCCScannerExtensionConfiguration.getInstance(scannerInfo); |
| } else { |
| configuration= GPPScannerExtensionConfiguration.getInstance(scannerInfo); |
| } |
| IScanner scanner; |
| scanner= new CPreprocessor(codeReader, scannerInfo, lang, NULL_LOG, configuration, |
| IncludeFileContentProvider.getSavedFilesProvider()); |
| return scanner; |
| } |
| |
| protected void validateSimplePostfixInitializerExpressionC(String code) throws ParserException { |
| ICASTTypeIdInitializerExpression e = (ICASTTypeIdInitializerExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| assertNotNull(e.getTypeId()); |
| assertNotNull(e.getInitializer()); |
| } |
| |
| protected void validateSimpleUnaryTypeIdExpression(String code, int op) throws ParserException { |
| IASTCastExpression e = (IASTCastExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| assertEquals(e.getOperator(), op); |
| assertNotNull(e.getTypeId()); |
| IASTIdExpression x = (IASTIdExpression) e.getOperand(); |
| assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$ |
| } |
| |
| protected void validateSimpleTypeIdExpressionC(String code, int op) throws ParserException { |
| IASTTypeIdExpression e = (IASTTypeIdExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| assertEquals(e.getOperator(), op); |
| assertNotNull(e.getTypeId()); |
| } |
| |
| protected void validateSimpleUnaryExpressionC(String code, int operator) throws ParserException { |
| IASTUnaryExpression e = (IASTUnaryExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| assertEquals(e.getOperator(), operator); |
| IASTIdExpression x = (IASTIdExpression) e.getOperand(); |
| assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$ |
| } |
| |
| protected void validateConditionalExpressionC(String code) throws ParserException { |
| IASTConditionalExpression e = (IASTConditionalExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| IASTIdExpression x = (IASTIdExpression) e.getLogicalConditionExpression(); |
| assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$ |
| IASTIdExpression y = (IASTIdExpression) e.getPositiveResultExpression(); |
| assertEquals(y.getName().toString(), "y"); //$NON-NLS-1$ |
| IASTIdExpression x2 = (IASTIdExpression) e.getNegativeResultExpression(); |
| assertEquals(x.getName().toString(), x2.getName().toString()); |
| } |
| |
| protected void validateSimpleBinaryExpressionC(String code, int operand) throws ParserException { |
| IASTBinaryExpression e = (IASTBinaryExpression) getExpressionFromStatementInCode(code, ParserLanguage.C); |
| assertNotNull(e); |
| assertEquals(e.getOperator(), operand); |
| IASTIdExpression x = (IASTIdExpression) e.getOperand1(); |
| assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$ |
| IASTIdExpression y = (IASTIdExpression) e.getOperand2(); |
| assertEquals(y.getName().toString(), "y"); //$NON-NLS-1$ |
| } |
| |
| protected IASTExpression getExpressionFromStatementInCode(String code, ParserLanguage language) throws ParserException { |
| StringBuilder buffer = new StringBuilder("void f() { "); //$NON-NLS-1$ |
| buffer.append("int x, y;\n"); //$NON-NLS-1$ |
| buffer.append(code); |
| buffer.append(";\n}"); //$NON-NLS-1$ |
| IASTTranslationUnit tu = parse(buffer.toString(), language); |
| IASTFunctionDefinition f = (IASTFunctionDefinition) tu.getDeclarations()[0]; |
| IASTCompoundStatement cs = (IASTCompoundStatement) f.getBody(); |
| IASTExpressionStatement s = (IASTExpressionStatement) cs.getStatements()[1]; |
| return s.getExpression(); |
| } |
| |
| protected <T extends IASTNode> T validateCopy(T tu) { |
| IASTNode copy = tu.copy(); |
| assertFalse(copy.isFrozen()); |
| ASTComparer.assertCopy(tu, copy); |
| return (T) copy; |
| } |
| |
| static protected class NameCollector extends ASTVisitor { |
| public NameCollector() { |
| this(false); // don't visit implicit names by default |
| } |
| |
| public NameCollector(boolean shouldVisitImplicitNames) { |
| this.shouldVisitNames = true; |
| this.shouldVisitImplicitNames = shouldVisitImplicitNames; |
| } |
| |
| public List<IASTName> nameList = new ArrayList<>(); |
| |
| @Override |
| public int visit(IASTName name) { |
| nameList.add(name); |
| return PROCESS_CONTINUE; |
| } |
| |
| public IASTName getName(int idx) { |
| if (idx < 0 || idx >= nameList.size()) |
| return null; |
| return nameList.get(idx); |
| } |
| |
| public int size() { |
| return nameList.size(); |
| } |
| |
| public void dump() { |
| for (int i= 0; i < size(); i++) { |
| IASTName name= getName(i); |
| String parent= name.getParent() != null ? name.getParent().getRawSignature() : ""; |
| System.out.println(i + ": #" + name.getRawSignature() + "# " + parent); |
| } |
| } |
| } |
| |
| protected void assertInstances(NameCollector collector, IBinding binding, int num) throws Exception { |
| int count = 0; |
| for (int i = 0; i < collector.size(); i++) { |
| if (collector.getName(i).resolveBinding() == binding) |
| count++; |
| } |
| |
| assertEquals(num, count); |
| } |
| |
| protected static void assertSameType(IType expected, IType actual) { |
| assertNotNull(expected); |
| assertNotNull(actual); |
| assertTrue("Expected same types, but the types were: '" + |
| ASTTypeUtil.getType(expected, false) + "' and '" + ASTTypeUtil.getType(actual, false) + "'", |
| expected.isSameType(actual)); |
| } |
| |
| protected void isExpressionStringEqual(IASTInitializerClause exp, String str) { |
| String expressionString = ASTStringUtil.getExpressionString((IASTExpression) exp); |
| assertEquals(str, expressionString); |
| } |
| |
| protected void isExpressionStringEqual(IASTExpression exp, String str) { |
| String expressionString = ASTStringUtil.getExpressionString(exp); |
| assertEquals(str, expressionString); |
| } |
| |
| protected void isParameterSignatureEqual(IASTDeclarator decltor, String str) { |
| assertTrue(decltor instanceof IASTFunctionDeclarator); |
| final String[] sigArray = ASTStringUtil.getParameterSignatureArray((IASTFunctionDeclarator) decltor); |
| assertEquals(str, "(" + ASTStringUtil.join(sigArray, ", ") + ")"); |
| } |
| |
| protected void isSignatureEqual(IASTDeclarator declarator, String expected) { |
| String signature= ASTStringUtil.getSignatureString(declarator); |
| assertEquals(expected, signature); |
| } |
| |
| protected void isSignatureEqual(IASTDeclSpecifier declSpec, String str) { |
| assertEquals(str, ASTStringUtil.getSignatureString(declSpec, null)); |
| } |
| |
| protected void isSignatureEqual(IASTTypeId typeId, String str) { |
| assertEquals(str, ASTStringUtil.getSignatureString(typeId.getDeclSpecifier(), typeId.getAbstractDeclarator())); |
| } |
| |
| protected void isTypeEqual(IASTDeclarator decltor, String str) { |
| assertEquals(str, ASTTypeUtil.getType(decltor)); |
| } |
| |
| protected void isTypeEqual(IASTTypeId typeId, String str) { |
| assertEquals(str, ASTTypeUtil.getType(typeId)); |
| } |
| |
| protected void isTypeEqual(IType type, String str) { |
| assertEquals(str, ASTTypeUtil.getType(type)); |
| } |
| |
| protected void isParameterTypeEqual(IFunctionType fType, String str) { |
| assertEquals(str, ASTTypeUtil.getParameterTypeString(fType)); |
| } |
| |
| static protected class CNameResolver extends ASTVisitor { |
| { |
| shouldVisitNames = true; |
| } |
| public int numProblemBindings; |
| public int numNullBindings; |
| public List<IASTName> nameList = new ArrayList<>(); |
| |
| @Override |
| public int visit(IASTName name) { |
| nameList.add(name); |
| IBinding binding = name.resolveBinding(); |
| if (binding instanceof IProblemBinding) |
| numProblemBindings++; |
| if (binding == null) |
| numNullBindings++; |
| return PROCESS_CONTINUE; |
| } |
| |
| public IASTName getName(int idx) { |
| if (idx < 0 || idx >= nameList.size()) |
| return null; |
| return nameList.get(idx); |
| } |
| |
| public int size() { |
| return nameList.size(); |
| } |
| } |
| |
| static protected class CPPNameResolver extends ASTVisitor { |
| { |
| shouldVisitNames = true; |
| } |
| public int numProblemBindings; |
| public int numNullBindings; |
| public List<IASTName> nameList = new ArrayList<>(); |
| |
| @Override |
| public int visit(IASTName name) { |
| nameList.add(name); |
| IBinding binding = name.resolveBinding(); |
| if (binding instanceof IProblemBinding) |
| numProblemBindings++; |
| if (binding == null) |
| numNullBindings++; |
| return PROCESS_CONTINUE; |
| } |
| |
| public IASTName getName(int idx) { |
| if (idx < 0 || idx >= nameList.size()) |
| return null; |
| return nameList.get(idx); |
| } |
| |
| public int size() { |
| return nameList.size(); |
| } |
| } |
| |
| protected String getAboveComment() throws IOException { |
| return getContents(1)[0].toString(); |
| } |
| |
| protected CharSequence[] getContents(int sections) throws IOException { |
| CTestPlugin plugin = CTestPlugin.getDefault(); |
| if (plugin == null) |
| throw new AssertionFailedError("This test must be run as a JUnit plugin test"); |
| return TestSourceReader.getContentsForTest(plugin.getBundle(), "parser", getClass(), getName(), sections); |
| } |
| |
| protected static void assertField(IBinding binding, String fieldName, String ownerName) { |
| assertInstance(binding, IField.class); |
| assertEquals(fieldName, binding.getName()); |
| ICompositeType struct = ((IField) binding).getCompositeTypeOwner(); |
| assertEquals(ownerName, struct.getName()); |
| } |
| |
| protected static void assertConstantValue(long expected, IVariable constant) { |
| IValue value = constant.getInitialValue(); |
| assertNotNull(value); |
| Number numericalValue = value.numberValue(); |
| assertNotNull(numericalValue); |
| assertEquals(expected, numericalValue.longValue()); |
| } |
| |
| protected class BindingAssertionHelper { |
| protected IASTTranslationUnit tu; |
| protected String contents; |
| protected boolean isCPP; |
| |
| public BindingAssertionHelper(String contents, boolean isCPP) throws ParserException { |
| this(contents, isCPP ? ParserLanguage.CPP : ParserLanguage.C); |
| } |
| |
| public BindingAssertionHelper(String contents, ParserLanguage lang) throws ParserException { |
| this.contents= contents; |
| this.isCPP= lang.isCPP(); |
| this.tu= parse(contents, lang, true, false); |
| } |
| |
| public IASTTranslationUnit getTranslationUnit() { |
| return tu; |
| } |
| |
| public IProblemBinding assertProblem(String section, int len) { |
| if (len <= 0) |
| len= section.length() + len; |
| IBinding binding= binding(section, len); |
| assertTrue("Non-ProblemBinding for name: " + section.substring(0, len), |
| binding instanceof IProblemBinding); |
| return (IProblemBinding) binding; |
| } |
| |
| public IProblemBinding assertProblem(String context, int len, int problemId) { |
| IProblemBinding problemBinding = assertProblem(context, len); |
| assertEquals(problemId, problemBinding.getID()); |
| return problemBinding; |
| } |
| |
| public IProblemBinding assertProblem(String context, String name) { |
| IBinding binding= binding(context, name); |
| assertTrue("Non-ProblemBinding for name: " + name, binding instanceof IProblemBinding); |
| return (IProblemBinding) binding; |
| } |
| |
| public IProblemBinding assertProblem(String context, String name, int problemId) { |
| IProblemBinding problemBinding = assertProblem(context, name); |
| assertEquals(problemId, problemBinding.getID()); |
| return problemBinding; |
| } |
| |
| public <T extends IBinding> T assertNonProblem(String section, int len) { |
| if (len <= 0) |
| len= section.length() + len; |
| IBinding binding= binding(section, len); |
| if (binding instanceof IProblemBinding) { |
| IProblemBinding problem= (IProblemBinding) binding; |
| fail("ProblemBinding for name: " + section.substring(0, len) + " (" + renderProblemID(problem.getID()) + ")"); |
| } |
| if (binding == null) { |
| fail("Null binding resolved for name: " + section.substring(0, len)); |
| } |
| return (T) binding; |
| } |
| |
| private int getIdentifierOffset(String str) { |
| for (int i = 0; i < str.length(); ++i) { |
| if (Character.isJavaIdentifierPart(str.charAt(i))) |
| return i; |
| } |
| fail("Didn't find identifier in \"" + str + "\""); |
| return -1; |
| } |
| |
| private int getIdentifierLength(String str, int offset) { |
| int i; |
| for (i = offset; i < str.length() && Character.isJavaIdentifierPart(str.charAt(i)); ++i) { |
| } |
| return i; |
| } |
| |
| public IProblemBinding assertProblemOnFirstIdentifier(String section) { |
| int offset = getIdentifierOffset(section); |
| String identifier = section.substring(offset, getIdentifierLength(section, offset)); |
| return assertProblem(section, identifier); |
| } |
| |
| public IProblemBinding assertProblemOnFirstIdentifier(String section, int problemId) { |
| IProblemBinding problemBinding = assertProblemOnFirstIdentifier(section); |
| assertEquals(problemId, problemBinding.getID()); |
| return problemBinding; |
| } |
| |
| public <T extends IBinding> T assertNonProblemOnFirstIdentifier(String section, Class... cs) { |
| int offset = getIdentifierOffset(section); |
| String identifier = section.substring(offset, getIdentifierLength(section, offset)); |
| return assertNonProblem(section, identifier, cs); |
| } |
| |
| public void assertNoName(String section, int len) { |
| IASTName name= findName(section, len); |
| if (name != null) { |
| String selection = section.substring(0, len); |
| fail("Found unexpected \"" + selection + "\": " + name.resolveBinding()); |
| } |
| } |
| |
| /** |
| * Asserts that there is exactly one name at the given location and that |
| * it resolves to the given type of binding. |
| */ |
| public IASTImplicitName assertImplicitName(String section, int len, Class<?> bindingClass) { |
| IASTName name = findImplicitName(section, len); |
| final String selection = section.substring(0, len); |
| assertNotNull("Did not find \"" + selection + "\"", name); |
| |
| assertInstance(name, IASTImplicitName.class); |
| IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent(); |
| IASTImplicitName[] implicits = owner.getImplicitNames(); |
| assertNotNull(implicits); |
| |
| if (implicits.length > 1) { |
| boolean found = false; |
| for (IASTImplicitName n : implicits) { |
| if (((ASTNode) n).getOffset() == ((ASTNode) name).getOffset()) { |
| assertFalse(found); |
| found = true; |
| } |
| } |
| assertTrue(found); |
| } |
| |
| assertEquals(selection, name.getRawSignature()); |
| IBinding binding = name.resolveBinding(); |
| assertNotNull(binding); |
| assertInstance(binding, bindingClass); |
| return (IASTImplicitName) name; |
| } |
| |
| public void assertNoImplicitName(String section, int len) { |
| IASTName name = findImplicitName(section, len); |
| final String selection = section.substring(0, len); |
| assertNull("found name \"" + selection + "\"", name); |
| } |
| |
| public IASTImplicitName[] getImplicitNames(String section) { |
| return getImplicitNames(section, section.length()); |
| } |
| |
| public IASTImplicitName[] getImplicitNames(String section, int len) { |
| IASTName name = findImplicitName(section, len); |
| IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent(); |
| IASTImplicitName[] implicits = owner.getImplicitNames(); |
| return implicits; |
| } |
| |
| public IASTImplicitDestructorName[] getImplicitDestructorNames(String section) { |
| return getImplicitDestructorNames(section, section.length()); |
| } |
| |
| public IASTImplicitDestructorName[] getImplicitDestructorNames(String section, int len) { |
| final int offset = contents.indexOf(section); |
| assertTrue(offset >= 0); |
| IASTNodeSelector selector = tu.getNodeSelector(null); |
| IASTNode enclosingNode = selector.findEnclosingNode(offset, len); |
| if (!(enclosingNode instanceof IASTImplicitDestructorNameOwner)) |
| return IASTImplicitDestructorName.EMPTY_NAME_ARRAY; |
| return ((IASTImplicitDestructorNameOwner) enclosingNode).getImplicitDestructorNames(); |
| } |
| |
| public IASTName findName(String section, int len) { |
| final int offset = contents.indexOf(section); |
| assertTrue("Section \"" + section + "\" not found", offset >= 0); |
| IASTNodeSelector selector = tu.getNodeSelector(null); |
| return selector.findName(offset, len); |
| } |
| |
| public IASTName findName(String context, String name) { |
| if (context == null) { |
| context = contents; |
| } |
| int offset = contents.indexOf(context); |
| assertTrue("Context \"" + context + "\" not found", offset >= 0); |
| int nameOffset = context.indexOf(name); |
| assertTrue("Name \"" + name + "\" not found", nameOffset >= 0); |
| IASTNodeSelector selector = tu.getNodeSelector(null); |
| return selector.findName(offset + nameOffset, name.length()); |
| } |
| |
| public IASTName findName(String name) { |
| return findName(contents, name); |
| } |
| |
| public IASTImplicitName findImplicitName(String section, int len) { |
| final int offset = contents.indexOf(section); |
| assertTrue(offset >= 0); |
| IASTNodeSelector selector = tu.getNodeSelector(null); |
| return selector.findImplicitName(offset, len); |
| } |
| |
| public <T extends IASTNode> T assertNode(String context, String nodeText, Class... cs) { |
| if (context == null) { |
| context = contents; |
| } |
| int offset = contents.indexOf(context); |
| assertTrue("Context \"" + context + "\" not found", offset >= 0); |
| int nodeOffset = context.indexOf(nodeText); |
| assertTrue("Node \"" + nodeText + "\" not found", nodeOffset >= 0); |
| IASTNodeSelector selector = tu.getNodeSelector(null); |
| IASTNode node = selector.findNode(offset + nodeOffset, nodeText.length()); |
| return assertType(node, cs); |
| } |
| |
| public <T extends IASTNode> T assertNode(String nodeText, Class... cs) { |
| return assertNode(contents, nodeText, cs); |
| } |
| |
| private String renderProblemID(int i) { |
| try { |
| for (Field field : IProblemBinding.class.getDeclaredFields()) { |
| if (field.getName().startsWith("SEMANTIC_")) { |
| if (field.getType() == int.class) { |
| Integer ci= (Integer) field.get(null); |
| if (ci.intValue() == i) { |
| return field.getName(); |
| } |
| } |
| } |
| } |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } |
| return "Unknown problem ID"; |
| } |
| |
| public <T extends IBinding> T assertNonProblem(String section, int len, Class... cs) { |
| if (len <= 0) |
| len += section.length(); |
| IBinding binding= binding(section, len); |
| assertTrue("ProblemBinding for name: " + section.substring(0, len), |
| !(binding instanceof IProblemBinding)); |
| return assertType(binding, cs); |
| } |
| |
| public <T extends IBinding> T assertNonProblem(String section, Class... cs) { |
| return assertNonProblem(section, section.length(), cs); |
| } |
| |
| public <T extends IBinding> T assertNonProblem(String context, String name, Class... cs) { |
| IBinding binding= binding(context, name); |
| assertTrue("ProblemBinding for name: " + name, !(binding instanceof IProblemBinding)); |
| return assertType(binding, cs); |
| } |
| |
| public void assertVariableType(String variableName, IType expectedType) { |
| IVariable var = assertNonProblem(variableName); |
| assertSameType(expectedType, var.getType()); |
| } |
| |
| public void assertVariableValue(String variableName, long expectedValue) { |
| IVariable var = assertNonProblem(variableName); |
| BaseTestCase.assertVariableValue(var, expectedValue); |
| } |
| |
| public <T, U extends T> U assertType(T obj, Class... cs) { |
| for (Class c : cs) { |
| assertInstance(obj, c); |
| } |
| return (U) obj; |
| } |
| |
| private IBinding binding(String section, int len) { |
| IASTName astName = findName(section, len); |
| final String selection = section.substring(0, len); |
| assertNotNull("No AST name for \"" + selection + "\"", astName); |
| assertEquals(selection, astName.getRawSignature()); |
| |
| IBinding binding = astName.resolveBinding(); |
| assertNotNull("No binding for " + astName.getRawSignature(), binding); |
| |
| return astName.resolveBinding(); |
| } |
| |
| private IBinding binding(String context, String name) { |
| IASTName astName = findName(context, name); |
| assertNotNull("No AST name for \"" + name + "\"", astName); |
| assertEquals(name, astName.getRawSignature()); |
| |
| IBinding binding = astName.resolveBinding(); |
| assertNotNull("No binding for " + astName.getRawSignature(), binding); |
| |
| return astName.resolveBinding(); |
| } |
| } |
| |
| final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang) throws Exception { |
| return parseAndCheckBindings(code, lang, false); |
| } |
| |
| final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang, boolean useGnuExtensions) throws Exception { |
| return parseAndCheckBindings(code, lang, useGnuExtensions, Integer.MAX_VALUE); |
| } |
| |
| final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang, boolean useGnuExtensions, |
| int limitTrivialInitializers) throws Exception { |
| IASTTranslationUnit tu = parse(code, lang, useGnuExtensions, true, limitTrivialInitializers); |
| NameCollector col = new NameCollector(); |
| tu.accept(col); |
| assertNoProblemBindings(col); |
| return tu; |
| } |
| |
| final protected IASTTranslationUnit parseAndCheckImplicitNameBindings() throws Exception { |
| IASTTranslationUnit tu = parse(getAboveComment(), CPP, false, true); |
| NameCollector col = new NameCollector(true /* Visit implicit names */); |
| tu.accept(col); |
| assertNoProblemBindings(col); |
| return tu; |
| } |
| |
| protected BindingAssertionHelper getAssertionHelper(ParserLanguage lang) throws ParserException, IOException { |
| String code= getAboveComment(); |
| return new BindingAssertionHelper(code, lang); |
| } |
| |
| final protected void assertNoProblemBindings(NameCollector col) { |
| for (IASTName n : col.nameList) { |
| assertFalse("ProblemBinding for " + n.getRawSignature(), n.resolveBinding() instanceof IProblemBinding); |
| } |
| } |
| |
| final protected void assertProblemBindings(NameCollector col, int count) { |
| int sum = 0; |
| for (IASTName n : col.nameList) { |
| if (n.resolveBinding() instanceof IProblemBinding) |
| ++sum; |
| } |
| assertEquals(count, sum); |
| } |
| |
| final protected <T extends IASTDeclaration> T getDeclaration(IASTTranslationUnit tu, int i_decl) { |
| Class<T> tclass; |
| IASTDeclaration[] decls= tu.getDeclarations(); |
| assertTrue(decls.length > i_decl); |
| return (T) decls[i_decl]; |
| } |
| |
| final protected <T extends IASTDeclaration> T getDeclaration(ICPPASTNamespaceDefinition ns, int i_decl) { |
| Class<T> tclass; |
| IASTDeclaration[] decls= ns.getDeclarations(); |
| assertTrue(decls.length > i_decl); |
| return (T) decls[i_decl]; |
| } |
| |
| final protected <T extends IASTDeclaration> T getDeclaration(ICPPASTLinkageSpecification ls, int i_decl) { |
| Class<T> tclass; |
| IASTDeclaration[] decls= ls.getDeclarations(); |
| assertTrue(decls.length > i_decl); |
| return (T) decls[i_decl]; |
| } |
| |
| final protected <T extends IASTDeclaration> T getDeclaration(IASTCompositeTypeSpecifier ct, int i_decl) { |
| Class<T> tclass; |
| IASTDeclaration[] decls= ct.getMembers(); |
| assertTrue(decls.length > i_decl); |
| return (T) decls[i_decl]; |
| } |
| |
| final protected <T extends IASTCompositeTypeSpecifier> T getCompositeType(IASTTranslationUnit tu, int i_decl) { |
| IASTSimpleDeclaration sdecl= getDeclaration(tu, i_decl); |
| return (T) sdecl.getDeclSpecifier(); |
| } |
| |
| final protected <T extends IASTStatement> T getStatement(IASTFunctionDefinition fdef, int i_stmt) { |
| return getStatement((IASTCompoundStatement) fdef.getBody(), i_stmt); |
| } |
| |
| final protected <T extends IASTStatement> T getStatement(IASTCompoundStatement compound, int i_stmt) { |
| IASTStatement[] stmts= compound.getStatements(); |
| assertTrue(stmts.length > i_stmt); |
| return (T) stmts[i_stmt]; |
| } |
| |
| final protected <T extends IASTExpression> T getExpressionOfStatement(IASTFunctionDefinition fdef, int i) { |
| IASTStatement stmt= getStatement(fdef, i); |
| assertInstance(stmt, IASTExpressionStatement.class); |
| return (T) ((IASTExpressionStatement) stmt).getExpression(); |
| } |
| |
| /** |
| * Sort the given array of AST names lexicographically. |
| */ |
| protected static <T extends IASTName> void sortNames(T[] names) { |
| Arrays.sort(names, new Comparator<IASTName>() { |
| @Override |
| public int compare(IASTName a, IASTName b) { |
| return a.toString().compareTo(b.toString()); |
| }}); |
| } |
| } |