/*******************************************************************************
* Copyright (c) 2009,2013 QNX Software Systems
* 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:
* QNX Software Systems (Alena Laskavaia) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.test;
import junit.framework.TestCase;
import org.eclipse.cdt.codan.core.CodanRuntime;
import org.eclipse.cdt.codan.core.model.IChecker;
import org.eclipse.cdt.codan.core.model.ICheckerInvocationContext;
import org.eclipse.cdt.codan.core.model.IProblemLocation;
import org.eclipse.cdt.codan.core.model.IProblemReporter;
import org.eclipse.cdt.codan.core.model.IRunnableInEditorChecker;
import org.eclipse.cdt.codan.internal.core.CheckerInvocationContext;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
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.IScannerInfo;
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.ast2.AST2TestBase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
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.GNUCPPSourceParser;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import java.io.IOException;
import java.util.ArrayList;
/**
* TODO: add description
*/
@SuppressWarnings({ "nls", "restriction" })
public abstract class CodanFastCxxAstTestCase extends TestCase {
protected IASTTranslationUnit tu;
protected String getAboveComment() {
return getContents(1)[0].toString();
}
protected StringBuilder[] getContents(int sections) {
try {
CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault();
return TestSourceReader.getContentsForTest(plugin == null ? null : plugin.getBundle(), "src", getClass(), getName(), sections);
} catch (IOException e) {
fail(e.getMessage());
return null;
}
}
public boolean isCpp() {
return false;
}
private static final NullLogService NULL_LOG = new NullLogService();
/**
* @return
*
*/
public IASTTranslationUnit parse(String code) {
return parse(code, isCpp() ? ParserLanguage.CPP : ParserLanguage.C, true);
}
protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean gcc) {
FileContent codeReader = FileContent.create("code.c", code.toCharArray());
IScannerInfo scannerInfo = new ScannerInfo();
IScanner scanner = AST2TestBase.createScanner(codeReader, lang, ParserMode.COMPLETE_PARSE, scannerInfo);
ISourceCodeParser parser2 = null;
if (lang == ParserLanguage.CPP) {
ICPPParserExtensionConfiguration config = null;
if (gcc)
config = new GPPParserExtensionConfiguration();
else
config = new ANSICPPParserExtensionConfiguration();
parser2 = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config);
} else {
ICParserExtensionConfiguration config = null;
if (gcc)
config = new GCCParserExtensionConfiguration();
else
config = new ANSICParserExtensionConfiguration();
parser2 = new GNUCSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config);
}
IASTTranslationUnit tu = parser2.parse();
if (parser2.encounteredError() && !hasCodeErrors())
fail("PARSE FAILURE");
if (!hasCodeErrors()) {
if (lang == ParserLanguage.C) {
IASTProblem[] problems = CVisitor.getProblems(tu);
assertEquals(problems.length, 0);
} else if (lang == ParserLanguage.CPP) {
IASTProblem[] problems = CPPVisitor.getProblems(tu);
assertEquals(problems.length, 0);
}
}
this.tu = tu;
return tu;
}
/**
* Override if any of code that test tried to parse has errors, otherwise
* parse method would assert
*
* @return
*/
protected boolean hasCodeErrors() {
return false;
}
public class ProblemInstance {
String id;
IProblemLocation loc;
Object[] args;
/**
* @param id
* @param loc
* @param args
*/
public ProblemInstance(String id, IProblemLocation loc, Object[] args) {
this.id = id;
this.loc = loc;
this.args = args;
}
}
private ArrayList<ProblemInstance> codanproblems = new ArrayList<CodanFastCxxAstTestCase.ProblemInstance>();
void runCodan(String code) {
tu = parse(code);
runCodan(tu);
}
void runCodan(IASTTranslationUnit tu) {
IProblemReporter problemReporter = CodanRuntime.getInstance().getProblemReporter();
CodanRuntime.getInstance().setProblemReporter(new IProblemReporter() {
public void reportProblem(String problemId, IProblemLocation loc, Object... args) {
codanproblems.add(new ProblemInstance(problemId, loc, args));
}
});
ICheckerInvocationContext context = new CheckerInvocationContext(null);
try {
IChecker checker = getChecker();
((IRunnableInEditorChecker) checker).processModel(tu, context);
} finally {
CodanRuntime.getInstance().setProblemReporter(problemReporter);
context.dispose();
}
}
/**
* @return
*/
public abstract IChecker getChecker();
protected int line2offset(int linePar, String code) throws IOException {
byte[] bytes = code.getBytes();
int line = 1;
for (int j = 0; j < bytes.length; j++) {
byte c = bytes[j];
if (line >= linePar)
return j;
if (c == '\n')
line++;
}
return 0;
}
}