blob: c3dde20b6f0e122d2d6ef27746203e64143eb6ba [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 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
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.index.composite.CompositingNotImplementedError;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
import org.eclipse.cdt.internal.core.index.composite.c.CCompositesFactory;
import org.eclipse.cdt.internal.core.index.composite.cpp.CPPCompositesFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
public class CIndex implements IIndex {
/**
* If this constant is set, for logical index objects with only
* one fragment, composite binding wrappers will not be used.
*/
private static final boolean SPECIALCASE_SINGLES = true;
private final IIndexFragment[] fFragments;
private int fReadLock;
private ICompositesFactory cppCF, cCF, fCF;
/**
* Creates an index consisting of one or more fragments.
*
* @param fragments Fragments constituting the index. If there are extended fragments,
* they are located in the array after the PDOM fragments for the same project.
*/
public CIndex(IIndexFragment[] fragments) {
fFragments= fragments;
}
@Override
public IIndexBinding findBinding(IName name) throws CoreException {
if (name instanceof IIndexFragmentName) {
return adaptBinding(((IIndexFragmentName) name).getBinding());
} else if (name instanceof IASTName) {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBinding((IASTName) name);
} else {
for (IIndexFragment fragment : fFragments) {
IIndexFragmentBinding binding= fragment.findBinding((IASTName) name);
if (binding != null) {
return getCompositesFactory(binding.getLinkage().getLinkageID()).getCompositeBinding(binding);
}
}
}
}
return null;
}
@Override
public IIndexBinding[] findBindings(Pattern pattern, boolean isFullyQualified, IndexFilter filter,
IProgressMonitor monitor) throws CoreException {
return findBindings(new Pattern[] { pattern }, isFullyQualified, filter, monitor);
}
@Override
public IIndexBinding[] findBindings(Pattern[] patterns, boolean isFullyQualified, IndexFilter filter,
IProgressMonitor monitor) throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindings(patterns, isFullyQualified, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findBindings(patterns, isFullyQualified,
retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
@Override
public IIndexBinding[] findMacroContainers(Pattern pattern, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findMacroContainers(pattern, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findMacroContainers(pattern,
retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
@Override
public IIndexName[] findNames(IBinding binding, int flags) throws CoreException {
LinkedList<IIndexFragmentName> result= new LinkedList<IIndexFragmentName>();
if (binding instanceof ICPPUsingDeclaration) {
IBinding[] bindings= ((ICPPUsingDeclaration) binding).getDelegates();
if (bindings == null || bindings.length == 0) {
return new IIndexName[0];
}
if (bindings.length > 1) {
ArrayList<IIndexName> multi= new ArrayList<IIndexName>();
for (IBinding b : bindings) {
multi.addAll(Arrays.asList(findNames(b, flags)));
}
return multi.toArray(new IIndexName[multi.size()]);
}
binding= bindings[0];
}
// Collect the names from all fragments. Since the same file may be represented by multiple
// variants in one or more index fragments, we need to filter out duplicate names.
// See bug 192352.
// Read only fragments can be superseded by what the indexer writes into
// a writable fragment. Therefore names from a read-only fragement are
// ignored if there is a match in a writable fragment.
HashSet<NameKey> encounteredNames = new HashSet<NameKey>();
for (IIndexFragment fragment : fFragments) {
if (fragment instanceof IWritableIndexFragment) {
final IIndexFragmentName[] names = fragment.findNames(binding, flags);
for (IIndexFragmentName name : names) {
if (encounteredNames.add(new NameKey(name, true))) {
result.add(name);
}
}
}
}
for (IIndexFragment fragment : fFragments) {
if (!(fragment instanceof IWritableIndexFragment)) {
final IIndexFragmentName[] names = fragment.findNames(binding, flags);
for (IIndexFragmentName name : names) {
if (encounteredNames.add(new NameKey(name, false))) {
result.add(name);
}
}
}
}
return result.toArray(new IIndexName[result.size()]);
}
@Override
public IIndexName[] findDeclarations(IBinding binding) throws CoreException {
return findNames(binding, FIND_DECLARATIONS_DEFINITIONS);
}
@Override
public IIndexName[] findDefinitions(IBinding binding) throws CoreException {
return findNames(binding, FIND_DEFINITIONS);
}
@Override
public IIndexName[] findReferences(IBinding binding) throws CoreException {
return findNames(binding, FIND_REFERENCES);
}
@Override
@Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
for (IIndexFragment fragment : fFragments) {
IIndexFragmentFile candidate= fragment.getFile(linkageID, location);
if (candidate != null && candidate.hasContent()) {
return candidate;
}
}
return null;
}
@Override
public IIndexFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException {
for (IIndexFragment fragment : fFragments) {
IIndexFragmentFile candidate= fragment.getFile(linkageID, location, significantMacros);
if (candidate != null && candidate.hasContent()) {
return candidate;
}
}
return null;
}
@Override
public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<ISignificantMacros> handled = new HashSet<ISignificantMacros>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
for (IIndexFragment fragment : fFragments) {
IIndexFragmentFile[] candidates= fragment.getFiles(linkageID, location);
for (IIndexFragmentFile candidate : candidates) {
if (candidate.hasContent()) {
ISignificantMacros macroKey = candidate.getSignificantMacros();
if (handled.add(macroKey)) {
result.add(candidate);
}
}
}
}
if (result.isEmpty()) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
return result.toArray(new IIndexFile[result.size()]);
}
@Override
public IIndexFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<FileContentKey> keys = new HashSet<FileContentKey>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
for (IIndexFragment fragment : fFragments) {
IIndexFragmentFile[] candidates= fragment.getFiles(location);
for (IIndexFragmentFile candidate : candidates) {
if (candidate.hasContent()) {
if (keys.add(new FileContentKey(candidate.getLinkageID(), candidate.getLocation(), candidate.getSignificantMacros()))) {
result.add(candidate);
}
}
}
}
if (result.isEmpty()) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
return result.toArray(new IIndexFile[result.size()]);
}
@Override
public IIndexFile resolveInclude(IIndexInclude include) throws CoreException {
IIndexFragmentInclude fragmentInclude = (IIndexFragmentInclude) include;
IIndexFragmentFile result= fragmentInclude.getIncludes();
if (result == null)
return null;
if (result.hasContent()) {
return result;
}
return getFile(result.getLinkageID(), result.getLocation(), result.getSignificantMacros());
}
@Override
public IIndexInclude[] findIncludedBy(IIndexFile file) throws CoreException {
return findIncludedBy(file, 0);
}
@Override
public IIndexInclude[] findIncludedBy(IIndexFile file, int depth) throws CoreException {
List<IIndexInclude> result= new ArrayList<IIndexInclude>();
findIncludedBy(file.getLinkageID(), Collections.singletonList(file), result, depth,
new HashSet<FileContentKey>());
return result.toArray(new IIndexInclude[result.size()]);
}
public void findIncludedBy(int linkageID, List<IIndexFile> in, List<IIndexInclude> out, int depth,
HashSet<FileContentKey> handled) throws CoreException {
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
for (IIndexFile iIndexFile : in) {
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
for (IIndexFragment fragment : fFragments) {
IIndexInclude[] includedBy= fragment.findIncludedBy(file);
for (IIndexInclude include : includedBy) {
final IIndexFile includer = include.getIncludedBy();
FileContentKey key= new FileContentKey(linkageID, includer.getLocation(), includer.getSignificantMacros());
if (handled.add(key)) {
out.add(include);
if (nextLevel != null) {
nextLevel.add(includer);
}
}
}
}
}
if (nextLevel == null || nextLevel.isEmpty()) {
return;
}
if (depth > 0) {
depth--;
}
findIncludedBy(linkageID, nextLevel, out, depth, handled);
}
@Override
public IIndexInclude[] findIncludes(IIndexFile file) throws CoreException {
return findIncludes(file, 0);
}
@Override
public IIndexInclude[] findIncludes(IIndexFile file, int depth) throws CoreException {
List<IIndexInclude> result= new ArrayList<IIndexInclude>();
findIncludes(Collections.singletonList(file), result, depth, new HashSet<Object>());
return result.toArray(new IIndexInclude[result.size()]);
}
private void findIncludes(List<IIndexFile> in, List<IIndexInclude> out, int depth,
HashSet<Object> handled) throws CoreException {
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
for (IIndexFile iIndexFile : in) {
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
IIndexInclude[] includes= file.getIncludes();
for (IIndexInclude include : includes) {
IIndexFileLocation target= include.getIncludesLocation();
Object key= target != null ? (Object) target : include.getFullName();
if (handled.add(key)) {
out.add(include);
if (nextLevel != null) {
IIndexFile includedByFile= resolveInclude(include);
if (includedByFile != null) {
nextLevel.add(includedByFile);
}
}
}
}
}
if (nextLevel == null || nextLevel.isEmpty()) {
return;
}
if (depth > 0) {
depth--;
}
findIncludes(nextLevel, out, depth, handled);
}
@Override
public synchronized void acquireReadLock() throws InterruptedException {
if (++fReadLock == 1) {
int i= 0;
try {
for (i = 0; i < fFragments.length; i++) {
fFragments[i].acquireReadLock();
}
} finally {
if (i < fFragments.length) {
// rollback
fReadLock--;
while (--i >= 0) {
fFragments[i].releaseReadLock();
}
}
}
}
}
@Override
public synchronized void releaseReadLock() {
if (--fReadLock == 0) {
for (IIndexFragment fragment : fFragments) {
fragment.releaseReadLock();
}
}
}
protected synchronized int getReadLockCount() {
return fReadLock;
}
@Override
public boolean hasWaitingReaders() {
for (IIndexFragment fragment : fFragments) {
if (fragment.hasWaitingReaders()) {
return true;
}
}
return false;
}
@Override
public long getLastWriteAccess() {
long result= 0;
for (IIndexFragment fragment : fFragments) {
result= Math.max(result, fragment.getLastWriteAccess());
}
return result;
}
@Override
public IIndexBinding[] findBindings(char[][] names, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
try {
return fFragments[0].findBindings(names, filter, monitor);
} catch (CoreException e) {
CCorePlugin.log(e);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
} else {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
monitor.beginTask(Messages.CIndex_FindBindingsTask_label, fFragments.length * linkages.length);
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findBindings(names,
retargetFilter(linkage, filter), new SubProgressMonitor(monitor, 1));
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
monitor.done();
return flatten(result);
}
}
@Override
public IIndexBinding adaptBinding(IBinding binding) {
try {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].adaptBinding(binding);
} else {
for (IIndexFragment fragment : fFragments) {
IIndexFragmentBinding adaptedBinding= fragment.adaptBinding(binding);
if (adaptedBinding != null) {
return getCompositesFactory(binding.getLinkage().getLinkageID()).getCompositeBinding(adaptedBinding);
}
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
return null;
}
@Override
public IIndexBinding[] findBindings(char[] name, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
return findBindings(name, true, filter, monitor);
}
/*
* Non-API
*/
private IIndexBinding[] flatten(List<IIndexBinding[]> bindingArrays) {
int size = 0;
for (int i = 0; i<bindingArrays.size(); i++) {
size += bindingArrays.get(i).length;
}
IIndexBinding[] result = new IIndexBinding[size];
int offset = 0;
for (int i = 0; i<bindingArrays.size(); i++) {
IBinding[] src = bindingArrays.get(i);
System.arraycopy(src, 0, result, offset, src.length);
offset += src.length;
}
return result;
}
public IIndexFragment[] getFragments() {
return fFragments;
}
public IIndexFragmentBinding[] findEquivalentBindings(IBinding binding) throws CoreException {
List<IIndexFragmentBinding> result = new ArrayList<IIndexFragmentBinding>();
for (IIndexFragment fragment : fFragments) {
IIndexFragmentBinding adapted = fragment.adaptBinding(binding);
if (adapted != null) {
result.add(adapted);
}
}
return result.toArray(new IIndexFragmentBinding[result.size()]);
}
private ICompositesFactory getCompositesFactory(int linkageID) {
switch (linkageID) {
case ILinkage.CPP_LINKAGE_ID:
if (cppCF == null) {
cppCF = new CPPCompositesFactory(this);
}
return cppCF;
case ILinkage.C_LINKAGE_ID:
if (cCF == null) {
cCF = new CCompositesFactory(this);
}
return cCF;
case ILinkage.FORTRAN_LINKAGE_ID:
if (fCF == null) {
fCF = new CCompositesFactory(this);
}
// This is a placeholder - it will throw CompositingNotImplementedError
// if non-empty (non-c) results are returned by a fragment
return fCF;
}
throw new CompositingNotImplementedError();
}
private IndexFilter retargetFilter(final ILinkage linkage, final IndexFilter filter) {
return new IndexFilter() {
@Override
public boolean acceptBinding(IBinding binding) throws CoreException {
return filter.acceptBinding(binding);
}
@Override
public boolean acceptLinkage(ILinkage other) {
return linkage.getLinkageID() == other.getLinkageID();
}
};
}
@Override
public IIndexBinding[] findBindingsForPrefix(char[] prefix, boolean filescope, IndexFilter filter,
IProgressMonitor monitor) throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindingsForPrefix(prefix, filescope, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findBindingsForPrefix(prefix, filescope,
retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
@Override
public IIndexBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindingsForContentAssist(prefix, filescope, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findBindingsForContentAssist(prefix,
filescope, retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
@Override
public IIndexBinding[] findBindings(char[] name, boolean filescope, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindings(name, filescope, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
try {
IBinding[] part = fFragments[i].findBindings(name, filescope,
retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
@Override
public IIndexMacro[] findMacros(char[] name, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
return findMacros(name, false, true, filter, monitor);
}
@Override
public IIndexMacro[] findMacrosForPrefix(char[] name, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
return findMacros(name, true, false, filter, monitor);
}
private IIndexMacro[] findMacros(char[] name, boolean isPrefix, boolean caseSensitive,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
// Macros can be represented multiple times when a header is parsed in c- and c++ context,
// so there is no special case for indexes with single fragments.
if (monitor == null) {
monitor= new NullProgressMonitor();
}
List<IIndexMacro> result = new ArrayList<IIndexMacro>();
HashSet<IIndexFileLocation> handledIFLs= new HashSet<IIndexFileLocation>();
monitor.beginTask(Messages.CIndex_FindBindingsTask_label, fFragments.length);
for (IIndexFragment fragment : fFragments) {
HashSet<IIndexFile> allowedFiles= new HashSet<IIndexFile>();
try {
IIndexMacro[] macros= fragment.findMacros(name, isPrefix, caseSensitive, filter,
new SubProgressMonitor(monitor, 1));
for (IIndexMacro indexMacro : macros) {
IIndexFile file= indexMacro.getFile();
if (!allowedFiles.contains(file)) {
if (handledIFLs.add(file.getLocation())) {
allowedFiles.add(file);
} else {
continue;
}
}
result.add(indexMacro);
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
monitor.done();
return result.toArray(new IIndexMacro[result.size()]);
}
public long getCacheHits() {
long result= 0;
for (IIndexFragment fragment : fFragments) {
result += fragment.getCacheHits();
}
return result;
}
public long getCacheMisses() {
long result= 0;
for (IIndexFragment fragment : fFragments) {
result += fragment.getCacheMisses();
}
return result;
}
public void resetCacheCounters() {
for (IIndexFragment fragment : fFragments) {
fragment.resetCacheCounters();
}
}
protected void clearResultCache() {
for (IIndexFragment frag : fFragments) {
frag.clearResultCache();
}
}
@Override
public IIndexFileSet createFileSet() {
return new IndexFileSet();
}
@Override
public IIndexFile[] getAllFiles() throws CoreException {
HashMap<IIndexFileLocation, IIndexFile> result= new HashMap<IIndexFileLocation, IIndexFile>();
for (IIndexFragment fragment : fFragments) {
for (IIndexFragmentFile file : fragment.getAllFiles()) {
if (file.hasContent()) {
result.put(file.getLocation(), file);
}
}
}
return result.values().toArray(new IIndexFile[result.size()]);
}
@Override
public IIndexFile[] getDefectiveFiles() throws CoreException {
HashMap<IIndexFileLocation, IIndexFile> result= new HashMap<IIndexFileLocation, IIndexFile>();
for (IIndexFragment fragment : fFragments) {
for (IIndexFragmentFile file : fragment.getDefectiveFiles()) {
if (file.hasContent()) {
result.put(file.getLocation(), file);
}
}
}
return result.values().toArray(new IIndexFile[result.size()]);
}
@Override
public IIndexFile[] getFilesWithUnresolvedIncludes() throws CoreException {
HashMap<IIndexFileLocation, IIndexFile> result= new HashMap<IIndexFileLocation, IIndexFile>();
for (IIndexFragment fragment : fFragments) {
for (IIndexFragmentFile file : fragment.getFilesWithUnresolvedIncludes()) {
if (file.hasContent()) {
result.put(file.getLocation(), file);
}
}
}
return result.values().toArray(new IIndexFile[result.size()]);
}
@Override
public IIndexScope[] getInlineNamespaces() throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].getInlineNamespaces();
}
IIndexFragmentBinding[][] preresult = new IIndexFragmentBinding[fFragments.length][];
for (int i = 0; i < fFragments.length; i++) {
IIndexScope[] raw = fFragments[i].getInlineNamespaces();
IIndexFragmentBinding[] arr = preresult[i] = new IIndexFragmentBinding[raw.length];
for (int j = 0; j < raw.length; j++) {
arr[j]= (IIndexFragmentBinding) raw[j].getScopeBinding();
}
}
IIndexBinding[] compBinding =
getCompositesFactory(ILinkage.CPP_LINKAGE_ID).getCompositeBindings(preresult);
IIndexScope[] result = new IIndexScope[compBinding.length];
for (int i = 0; i < result.length; i++) {
result[i]= (IIndexScope) ((ICPPNamespace) compBinding[i]).getNamespaceScope();
}
return result;
}
@Override
public boolean isFullyInitialized() {
for (IIndexFragment fragment : fFragments) {
if (!fragment.isFullyInitialized())
return false;
}
return true;
}
/**
* A key used to uniquely identify an IIndexFragmentName object. Uniqueness is guaranteed only
* for names corresponding to the same binding.
*/
private static final class NameKey {
private final IIndexFileLocation location;
private final int linkageID;
private final int offset;
private final boolean inWritableFragment;
NameKey(IIndexFragmentName name, boolean writable) throws CoreException {
IIndexFile file = name.getFile();
location = file.getLocation();
linkageID = file.getLinkageID();
offset = name.getNodeOffset();
inWritableFragment= writable;
}
@Override
public int hashCode() {
return location.hashCode() * 31 + linkageID;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NameKey other = (NameKey) obj;
// Offset is significant only if matches are from same kind of fragment
if (inWritableFragment == other.inWritableFragment && offset != other.offset)
return false;
if (linkageID != other.linkageID)
return false;
if (!location.equals(other.location))
return false;
return true;
}
}
}