/******************************************************************************* * Copyright (c) 2008, 2015 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.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.IIndexFileLocation; 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<>(); public IndexFileSet() { } @Override 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); } @Override 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); } } @Override public boolean containsDeclaration(IIndexBinding binding) { for (Map.Entry<IIndexFragment, IIndexFragmentFileSet> entry : fSubSets.entrySet()) { try { IIndexFragmentName[] names = entry.getKey().findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS); for (IIndexFragmentName name : names) { try { if (entry.getValue().contains((IIndexFragmentFile) name.getFile())) return true; } catch (CoreException e) { CCorePlugin.log(e); } } } catch (CoreException e) { CCorePlugin.log(e); } } return false; } @Override public boolean containsNonLocalDeclaration(IBinding binding, IIndexFragment ignore) { for (Map.Entry<IIndexFragment, IIndexFragmentFileSet> entry : fSubSets.entrySet()) { try { final IIndexFragment fragment = entry.getKey(); final IIndexFragmentFileSet subset = entry.getValue(); if (fragment != ignore) { IIndexFragmentName[] names = fragment.findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS | IIndexFragment.FIND_NON_LOCAL_ONLY); for (IIndexFragmentName name : names) { try { if (subset.contains((IIndexFragmentFile) name.getFile())) { return true; } } catch (CoreException e) { CCorePlugin.log(e); } } } } catch (CoreException e) { CCorePlugin.log(e); } } return false; } public boolean containsNonLocalDeclaration(IBinding binding, IIndexFileLocation ignore) { for (Map.Entry<IIndexFragment, IIndexFragmentFileSet> entry : fSubSets.entrySet()) { try { final IIndexFragment fragment = entry.getKey(); final IIndexFragmentFileSet subset = entry.getValue(); IIndexFragmentName[] names = fragment.findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS | IIndexFragment.FIND_NON_LOCAL_ONLY); for (IIndexFragmentName name : names) { try { IIndexFile file = name.getFile(); if (!file.getLocation().equals(ignore) && subset.contains((IIndexFragmentFile) file)) { return true; } } catch (CoreException e) { CCorePlugin.log(e); } } } catch (CoreException e) { CCorePlugin.log(e); } } return false; } @Override 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= 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; } @Override 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 fragmentFile= (IIndexFragmentFile) file; IIndexFragmentFileSet subSet= fSubSets.get(fragmentFile.getIndexFragment()); if (subSet != null && subSet.contains(fragmentFile)) { return !invert; } return invert; } @Override public IIndexFileSet invert() { if (fInverse == null) { fInverse= new IIndexFileSet() { @Override public IIndexFileSet invert() { return IndexFileSet.this; } @Override public IBinding[] filterFileLocalBindings(IBinding[] bindings) { return IndexFileSet.this.filterFileLocalBindings(bindings, true); } @Override public boolean containsDeclaration(IIndexBinding binding) { throw new UnsupportedOperationException(); } @Override public boolean containsNonLocalDeclaration(IBinding binding, IIndexFragment ignore) { throw new UnsupportedOperationException(); } @Override public boolean contains(IIndexFile file) throws CoreException { return IndexFileSet.this.contains(file, true); } @Override public void add(IIndexFile indexFile) { Assert.isLegal(false); } @Override public void remove(IIndexFile indexFile) { Assert.isLegal(false); } }; } return fInverse; } }