/******************************************************************************* * Copyright (c) 2005, 2013 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) *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.parser.ISourceCodeParser; 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.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.ICPPParserExtensionConfiguration; import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.IScanner; 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.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; 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.parser.ParserException; /** * @author dsteffle */ public class AST2SpecTestBase extends AST2TestBase { public AST2SpecTestBase() { super(); } public AST2SpecTestBase(String name) { super(name); } /** * checkSemantics is used to specify whether the example should have semantics checked * since several spec examples have syntactically correct code ONLY this flag was added * so that future tests can ensure that examples are checked against syntax/semantics where necessary * @param code * @param expectedProblemBindings the number of problem bindings you expect to encounter * @throws ParserException */ protected void parseCandCPP(String code, boolean checkBindings, int expectedProblemBindings) throws ParserException { parse(code, ParserLanguage.C, false, true, checkBindings, expectedProblemBindings, null); parse(code, ParserLanguage.CPP, false, true, checkBindings, expectedProblemBindings, null); } protected IASTTranslationUnit parseWithErrors(String code, ParserLanguage lang) throws ParserException { return parse(code, lang, false, false, false, 0, null); } protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean checkBindings, int expectedProblemBindings) throws ParserException { return parse(code, lang, false, true, checkBindings, expectedProblemBindings, null); } protected IASTTranslationUnit parse(String code, ParserLanguage lang, String[] problems) throws ParserException { return parse(code, lang, false, true, true, problems.length, problems); } private IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings, String[] problems) throws ParserException { // TODO beef this up with tests... i.e. run once with \n, and then run again with \r\n replacing \n ... etc // TODO another example might be to replace all characters with corresponding trigraph/digraph tests... FileContent codeReader = FileContent.create("<test-code>", code.toCharArray()); return parse(codeReader, lang, useGNUExtensions, expectNoProblems, checkBindings, expectedProblemBindings, problems); } // private IASTTranslationUnit parse(IFile filename, ParserLanguage lang, boolean useGNUExtensions, boolean expectNoProblems) throws ParserException { // CodeReader codeReader=null; // try { // codeReader = new CodeReader(filename.getName(), filename.getContents()); // } catch (IOException e) { // e.printStackTrace(); // } catch (CoreException e) { // e.printStackTrace(); // } // // return parse(codeReader, lang, useGNUExtensions, expectNoProblems); // } private IASTTranslationUnit parse(FileContent codeReader, ParserLanguage lang, boolean useGNUExtensions, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings, String[] problems) throws ParserException { ScannerInfo scannerInfo = new ScannerInfo(); IScanner scanner= AST2TestBase.createScanner(codeReader, lang, ParserMode.COMPLETE_PARSE, scannerInfo); ISourceCodeParser parser2 = null; if (lang == ParserLanguage.CPP) { ICPPParserExtensionConfiguration config = null; if (useGNUExtensions) config = new GPPParserExtensionConfiguration(); else config = new ANSICPPParserExtensionConfiguration(); parser2 = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config); } else { ICParserExtensionConfiguration config = null; if (useGNUExtensions) config = new GCCParserExtensionConfiguration(); else config = new ANSICParserExtensionConfiguration(); parser2 = new GNUCSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config); } if (expectedProblemBindings > 0) CPPASTNameBase.sAllowNameComputation= true; IASTTranslationUnit tu = parser2.parse(); // resolve all bindings if (checkBindings) { NameResolver res = new NameResolver(); tu.accept(res); if (res.problemBindings.size() != expectedProblemBindings) throw new ParserException("Expected " + expectedProblemBindings + " problems, encountered " + res.problemBindings.size()); if (problems != null) { for (int i = 0; i < problems.length; i++) { assertEquals(problems[i], res.problemBindings.get(i)); } } } if (parser2.encounteredError() && expectNoProblems) throw new ParserException("FAILURE"); if (lang == ParserLanguage.C && expectNoProblems) { if (CVisitor.getProblems(tu).length != 0) { throw new ParserException("CVisitor has AST Problems"); } if (tu.getPreprocessorProblems().length != 0) { throw new ParserException("C TranslationUnit has Preprocessor Problems"); } } else if (lang == ParserLanguage.CPP && expectNoProblems) { if (CPPVisitor.getProblems(tu).length != 0) { throw new ParserException("CPPVisitor has AST Problems"); } if (tu.getPreprocessorProblems().length != 0) { throw new ParserException("CPP TranslationUnit has Preprocessor Problems"); } } return tu; } static protected class NameResolver extends ASTVisitor { { shouldVisitNames = true; } public List<IASTName> nameList = new ArrayList<IASTName>(); public List<String> problemBindings = new ArrayList<String>(); public int numNullBindings = 0; @Override public int visit(IASTName name) { nameList.add(name); IBinding binding = name.resolveBinding(); if (binding instanceof IProblemBinding) problemBindings.add(name.toString()); 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(); } } }