/*******************************************************************************
* Copyright (c) 2008, 2010 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
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
public class IndexFileSet implements IIndexFileSet {
private IIndexFileSet fInverse;
private HashMap<IIndexFragment, IIndexFragmentFileSet> fSubSets= new HashMap<IIndexFragment, IIndexFragmentFileSet>();
public IndexFileSet() {
}
public void add(IIndexFile indexFile) {
final IIndexFragmentFile fragFile = (IIndexFragmentFile) indexFile;
final IIndexFragment frag= fragFile.getIndexFragment();
IIndexFragmentFileSet subSet= fSubSets.get(frag);
if (subSet == null) {
subSet= frag.createFileSet();
fSubSets.put(frag, subSet);
}
subSet.add(fragFile);
}
public void remove(IIndexFile indexFile) {
final IIndexFragmentFile fragFile = (IIndexFragmentFile) indexFile;
final IIndexFragment frag= fragFile.getIndexFragment();
IIndexFragmentFileSet subSet= fSubSets.get(frag);
if (subSet != null) {
subSet.remove(fragFile);
}
}
public boolean containsDeclaration(IIndexBinding binding) {
return containsDeclaration(binding, false);
}
boolean containsDeclaration(IIndexBinding binding, boolean inverse) {
for (Map.Entry<IIndexFragment, IIndexFragmentFileSet> entry : fSubSets.entrySet()) {
try {
IIndexFragmentName[] names =
entry.getKey().findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS);
for (IIndexFragmentName name : names) {
try {
final boolean foundDecl = entry.getValue().contains((IIndexFragmentFile) name.getFile());
if (foundDecl != inverse) {
return true;
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
return false;
}
public IBinding[] filterFileLocalBindings(IBinding[] bindings) {
return filterFileLocalBindings(bindings, false);
}
public IBinding[] filterFileLocalBindings(IBinding[] bindings, boolean invert) {
if (bindings == null || bindings.length == 0) {
return bindings;
}
BitSet ok= new BitSet(bindings.length);
if (invert) {
ok.set(0, bindings.length);
}
for (int i = 0; i < bindings.length; i++) {
IBinding binding = bindings[i];
if (binding != null) {
IIndexFragmentBinding fb;
if (binding instanceof IIndexFragmentBinding) {
fb= (IIndexFragmentBinding) binding;
}
else {
fb= (IIndexFragmentBinding) binding.getAdapter(IIndexFragmentBinding.class);
}
try {
if (fb != null && fb.isFileLocal()) {
IIndexFragmentFileSet subSet= fSubSets.get(fb.getFragment());
if (subSet != null && subSet.containsFileOfLocalBinding(fb)) {
ok.set(i);
}
}
else {
ok.set(i);
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}
if (invert) {
ok.flip(0, bindings.length);
}
final int cardinality = ok.cardinality();
if (cardinality == bindings.length) {
return bindings;
}
IBinding[] result= new IBinding[cardinality];
int j= ok.nextSetBit(0);
for (int i = 0; i < result.length; i++) {
result[i]= bindings[j];
j= ok.nextSetBit(j+1);
}
return result;
}
public boolean contains(IIndexFile file) throws CoreException {
return contains(file, false);
}
public boolean contains(IIndexFile file, boolean invert) throws CoreException {
if (!(file instanceof IIndexFragmentFile))
return invert;
IIndexFragmentFile ifile= (IIndexFragmentFile) file;
IIndexFragmentFileSet subSet= fSubSets.get(ifile.getIndexFragment());
if (subSet != null && subSet.contains(ifile)) {
return !invert;
}
return invert;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.index.IIndexFileSet#invert()
*/
public IIndexFileSet invert() {
if (fInverse == null) {
fInverse= new IIndexFileSet() {
public IIndexFileSet invert() {
return IndexFileSet.this;
}
public IBinding[] filterFileLocalBindings(IBinding[] bindings) {
return IndexFileSet.this.filterFileLocalBindings(bindings, true);
}
public boolean containsDeclaration(IIndexBinding binding) {
return IndexFileSet.this.containsDeclaration(binding, true);
}
public boolean contains(IIndexFile file) throws CoreException {
return IndexFileSet.this.contains(file, true);
}
public void add(IIndexFile indexFile) {
Assert.isLegal(false);
}
public void remove(IIndexFile indexFile) {
Assert.isLegal(false);
}
};
}
return fInverse;
}
}