/*******************************************************************************
* Copyright (c) 2007, 2014 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.indexer;
import java.io.File;
import java.util.HashMap;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.parser.InternalParserUtil;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.UnusedHeaderStrategy;
import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter;
import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy;
import org.eclipse.cdt.utils.UNCPathConverter;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
/**
* Provides information about translation-units.
* @since 5.0
*/
public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
private static final boolean CASE_INSENSITIVE_FILE_SYSTEM = new File("a").equals(new File("A")); //$NON-NLS-1$//$NON-NLS-2$
private static final AbstractLanguage[] NO_LANGUAGE = new AbstractLanguage[0];
private final ICProject fCProject;
private final HashMap<String, IIndexFileLocation> fIflCache;
private final FileExistsCache fExistsCache;
private AbstractLanguage fLangC;
private AbstractLanguage fLangCpp;
private String fProjectPrefix;
public ProjectIndexerInputAdapter(ICProject cproject) {
this(cproject, true);
}
public ProjectIndexerInputAdapter(ICProject cproject, boolean useCache) {
fCProject= cproject;
fProjectPrefix= cproject.getProject().getFullPath().toString() + IPath.SEPARATOR;
if (useCache) {
fIflCache= new HashMap<String, IIndexFileLocation>();
fExistsCache= new FileExistsCache(isCaseInsensitiveFileSystem());
} else {
fIflCache= null;
fExistsCache= null;
}
ILanguage l= LanguageManager.getInstance().getLanguageForContentTypeID(CCorePlugin.CONTENT_TYPE_CHEADER);
if (l instanceof AbstractLanguage) {
fLangC= (AbstractLanguage) l;
}
l= LanguageManager.getInstance().getLanguageForContentTypeID(CCorePlugin.CONTENT_TYPE_CXXHEADER);
if (l instanceof AbstractLanguage) {
fLangCpp= (AbstractLanguage) l;
}
}
@Override
public boolean isCaseInsensitiveFileSystem() {
if (Platform.OS_MACOSX.equals(Platform.getOS()))
return true;
return CASE_INSENSITIVE_FILE_SYSTEM;
}
@Override
public IIndexFileLocation resolveASTPath(String astPath) {
if (fIflCache == null) {
return doResolveASTPath(astPath);
}
IIndexFileLocation result= fIflCache.get(astPath);
if (result == null) {
result = doResolveASTPath(astPath);
fIflCache.put(astPath, result);
}
return result;
}
private IIndexFileLocation doResolveASTPath(String astPath) {
return IndexLocationFactory.getIFLExpensive(fCProject, astPath);
}
@Override
public IIndexFileLocation resolveIncludeFile(String includePath) {
if (fIflCache == null) {
return doResolveASTPath(includePath);
}
if (!fExistsCache.isFile(includePath)) {
return null;
}
IIndexFileLocation result= fIflCache.get(includePath);
if (result == null) {
result = doResolveASTPath(includePath);
if (result.getFullPath() == null && !UNCPathConverter.isUNC(includePath)) {
File location= new File(includePath);
String canonicalPath= PathCanonicalizationStrategy.getCanonicalPath(location);
if (!includePath.equals(canonicalPath)) {
result= IndexLocationFactory.getExternalIFL(canonicalPath);
fIflCache.put(canonicalPath, result);
}
}
fIflCache.put(includePath, result);
}
return result;
}
@Override
public boolean doesIncludeFileExist(String includePath) {
if (fExistsCache != null) {
return fExistsCache.isFile(includePath);
}
return new File(includePath).isFile();
}
@Override
public long getFileSize(String astFilePath) {
return new File(astFilePath).length();
}
@Override
public String getASTPath(IIndexFileLocation ifl) {
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
if (path != null) {
return path.toOSString();
}
return ifl.getURI().getPath();
}
@Override
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
IScannerInfo info= ((ITranslationUnit) tu).getScannerInfo(true);
if (info == null) {
info= new ExtendedScannerInfo();
}
return info;
}
@Override
public long getLastModified(IIndexFileLocation ifl) {
String fullPath= ifl.getFullPath();
if (fullPath != null) {
IResource res= ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(fullPath));
if (res != null) {
return res.getLocalTimeStamp();
}
return 0;
}
IPath location= IndexLocationFactory.getAbsolutePath(ifl);
if (location != null) {
return location.toFile().lastModified();
}
return 0;
}
@Override
public long getFileSize(IIndexFileLocation ifl) {
String fullPath= ifl.getFullPath();
IPath location= null;
if (fullPath != null) {
IResource res= ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(fullPath));
if (res != null) {
location = res.getLocation();
}
} else {
location= IndexLocationFactory.getAbsolutePath(ifl);
}
if (location != null) {
return location.toFile().length();
}
return 0;
}
@Override
public String getEncoding(IIndexFileLocation ifl) {
String fullPath= ifl.getFullPath();
if (fullPath != null) {
IResource res= ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(fullPath));
if (res instanceof IFile) {
try {
return ((IFile) res).getCharset();
} catch (CoreException e) {
}
}
}
return InternalParserUtil.SYSTEM_DEFAULT_ENCODING;
}
@Override
public AbstractLanguage[] getLanguages(Object tuo, UnusedHeaderStrategy strategy) {
if (tuo instanceof PotentialTranslationUnit) {
if (fLangC != null) {
if (fLangCpp != null) {
return new AbstractLanguage[] {fLangC, fLangCpp};
}
return new AbstractLanguage[] {fLangC};
}
if (fLangCpp != null) {
return new AbstractLanguage[] {fLangCpp};
}
return NO_LANGUAGE;
}
ITranslationUnit tu= (ITranslationUnit) tuo;
try {
ILanguage lang= tu.getLanguage();
if (lang instanceof AbstractLanguage) {
final boolean both = strategy == UnusedHeaderStrategy.useBoth;
final boolean useC = strategy == UnusedHeaderStrategy.useC;
final boolean useCpp = strategy == UnusedHeaderStrategy.useCPP;
if ((both || useC || useCpp) && tu.isHeaderUnit()) {
String filename= tu.getElementName();
if (filename.indexOf('.') >= 0) {
final String contentTypeId= tu.getContentTypeId();
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CXXHEADER) && fLangC != null) {
if (both)
return new AbstractLanguage[] {(AbstractLanguage) lang, fLangC};
if (useC)
return new AbstractLanguage[] {fLangC};
} else if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CHEADER) && fLangCpp != null) {
if (both)
return new AbstractLanguage[] {(AbstractLanguage) lang, fLangCpp};
if (useCpp)
return new AbstractLanguage[] {fLangCpp};
}
}
}
return new AbstractLanguage[] {(AbstractLanguage) lang};
}
}
catch (CoreException e) {
CCorePlugin.log(e);
}
return NO_LANGUAGE;
}
@Override
public boolean isFileBuildConfigured(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;
return !CoreModel.isScannerInformationEmpty(tu.getResource());
}
@Override
public boolean isIndexedOnlyIfIncluded(Object tu) {
return tu instanceof PotentialTranslationUnit;
}
@Override
public boolean isIndexedUnconditionally(IIndexFileLocation ifl) {
return CCoreInternals.getPDOMManager().isFileIndexedUnconditionally(ifl);
}
@Override
public int getIndexingPriority(IIndexFileLocation ifl) {
return CCoreInternals.getPDOMManager().getIndexingPriority(ifl);
}
@Override
public boolean isSourceUnit(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;
return tu.isSourceUnit();
}
@Override
public boolean isSource(String filename) {
IContentType ct= CCorePlugin.getContentType(fCProject.getProject(), filename);
if (ct != null) {
String id = ct.getId();
if (CCorePlugin.CONTENT_TYPE_CSOURCE.equals(id) || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(id)) {
return true;
}
}
return false;
}
@Override
public IIndexFileLocation resolveFile(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;
return IndexLocationFactory.getIFL(tu);
}
@Override
public boolean canBePartOfSDK(IIndexFileLocation ifl) {
final String fullPath = ifl.getFullPath();
return fullPath == null || !fullPath.startsWith(fProjectPrefix);
}
@Override
public Object getInputFile(IIndexFileLocation location) {
try {
return CoreModelUtil.findTranslationUnitForLocation(location, fCProject);
} catch (CModelException e) {
CCorePlugin.log(e);
}
return null;
}
@Override
public FileContent getCodeReader(Object tuo) {
ITranslationUnit tu= (ITranslationUnit) tuo;
if (tu.getLocation() == null)
return null;
final FileContent reader= FileContent.create(tu);
if (reader != null) {
IIndexFileLocation ifl= IndexLocationFactory.getIFL(tu);
fIflCache.put(reader.getFileLocation(), ifl);
}
return reader;
}
}