/*******************************************************************************
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.CDOM;
import org.eclipse.cdt.core.dom.IASTServiceProvider.UnsupportedDialectException;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.refactoring.Container;
/**
* A collection of methods that deal with IASTTranslationUnits.
*
* @author Mirko Stocker
*/
public class TranslationUnitHelper {
private static final int AST_STYLE = ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT | ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
/**
* Visits all names in the TU to find the specified name
*/
public static IASTName findNameInTranslationUnit(IASTTranslationUnit transUnit, IASTNode oldName) {
final String oldFileName = oldName.getFileLocation().getFileName();
final IASTFileLocation pos = oldName.getFileLocation();
final Container<IASTName> nameCon = new Container<IASTName>();
transUnit.accept(new ASTVisitor() {
{
shouldVisitNames = true;
}
@Override
public int visit(IASTName locName) {
IASTFileLocation locFileLocation = locName.getFileLocation();
if (locFileLocation != null && oldFileName.equals(locFileLocation.getFileName()) && pos.getNodeOffset() == locFileLocation.getNodeOffset()
&& pos.getNodeLength() == locFileLocation.getNodeLength()) {
nameCon.setObject(locName);
return PROCESS_ABORT;
}
return super.visit(locName);
}
});
return nameCon.getObject();
}
/**
* @return the first node in the translation unit or null
*/
public static IASTNode getFirstNode(IASTTranslationUnit unit) {
IASTDeclaration firstNode = null;
for (IASTDeclaration each : unit.getDeclarations()) {
if (firstNode == null) {
firstNode = each;
} else if (each.getNodeLocations() != null &&
each.getNodeLocations()[0].getNodeOffset() < firstNode.getNodeLocations()[0].getNodeOffset()) {
firstNode = each;
}
}
return firstNode;
}
/**
* @param filename to load the translation unit from
* @return the translation unit for the file or null
* @throws CoreException
* @deprecated Use RefactoringASTCache.
*/
@Deprecated
public static IASTTranslationUnit loadTranslationUnit(String filename, boolean useIndex) throws CoreException{
if (filename != null) {
IFile[] tmpFile = null;
tmpFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(
URIUtil.toURI(filename));
return loadTranslationUnit(tmpFile[0], useIndex);
}
return null;
}
/**
* @param file to load the translation unit from
* @return the translation unit for the file or null
* @throws CoreException
* @deprecated Use RefactoringASTCache.
*/
@Deprecated
public static IASTTranslationUnit loadTranslationUnit(IFile file, boolean useIndex) throws CoreException {
if (file == null) {
return null;
}
if (useIndex) {
return loadIndexBasedTranslationUnit(file);
} else {
return loadFileBasedTranslationUnit(file);
}
}
private static IASTTranslationUnit loadFileBasedTranslationUnit(IFile file) {
try {
IASTTranslationUnit fileUnit = CDOM.getInstance().getTranslationUnit(file, CDOM.getInstance().getCodeReaderFactory(CDOM.PARSE_SAVED_RESOURCES), true);
return fileUnit;
} catch (UnsupportedDialectException e) {
return null;
}
}
private static IASTTranslationUnit loadIndexBasedTranslationUnit(IFile file) throws CoreException {
IIndex index = null;
try {
index = lockIndex();
ITranslationUnit tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create(file);
return tu.getAST(index, AST_STYLE);
} catch (InterruptedException e) {
CUIPlugin.log(e);
} finally {
unlockIndex(index);
}
return null;
}
private static IIndex lockIndex() throws CoreException, InterruptedException {
IIndex index;
ICProject[] projects= CoreModel.getDefault().getCModel().getCProjects();
index= CCorePlugin.getIndexManager().getIndex(projects);
try {
index.acquireReadLock();
} catch (InterruptedException e) {
// no lock was acquired
index= null;
throw e;
}
return index;
}
private static void unlockIndex(IIndex index) {
if (index != null) {
index.releaseReadLock();
}
}
}