/******************************************************************************* * Copyright (c) 2006, 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 * 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.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; 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.SubMonitor; 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<>(); 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<>(); 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 { ArrayList<IIndexFragmentName> result= new ArrayList<>(); if (binding instanceof ICPPUsingDeclaration) { IBinding[] bindings= ((ICPPUsingDeclaration) binding).getDelegates(); if (bindings == null || bindings.length == 0) { return IIndexName.EMPTY_ARRAY; } if (bindings.length > 1) { ArrayList<IIndexName> multi= new ArrayList<>(); 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 fragment are // ignored if there is a match in a writable fragment. HashSet<NameKey> encounteredNames = new HashSet<>(); 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<>(); ArrayList<IIndexFragmentFile> result= new ArrayList<>(); 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<>(); ArrayList<IIndexFragmentFile> result= new ArrayList<>(); 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<>(); Collection<IIndexFile> in = Collections.singletonList(file); Set<FileContentKey> handled = new HashSet<>(); while (true) { Collection<IIndexFile> nextLevel= depth != 0 ? new ArrayDeque<IIndexFile>() : null; for (IIndexFile indexFile : in) { IIndexFragmentFile file1 = (IIndexFragmentFile) indexFile; for (IIndexFragment fragment : fFragments) { IIndexInclude[] includedBy= fragment.findIncludedBy(file1); for (IIndexInclude include : includedBy) { final IIndexFile includer = include.getIncludedBy(); FileContentKey key= new FileContentKey(file.getLinkageID(), includer.getLocation(), includer.getSignificantMacros()); if (handled.add(key)) { result.add(include); if (nextLevel != null) { nextLevel.add(includer); } } } } } if (nextLevel == null || nextLevel.isEmpty()) { break; } if (depth > 0) { depth--; } in = nextLevel; } return result.toArray(new IIndexInclude[result.size()]); } @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<>(); Collection<IIndexFile> in = Collections.singletonList(file); Set<Object> handled = new HashSet<>(); while (true) { Collection<IIndexFile> nextLevel= depth != 0 ? new ArrayDeque<IIndexFile>() : null; for (IIndexFile indexFile : in) { IIndexFragmentFile file1 = (IIndexFragmentFile) indexFile; IIndexInclude[] includes= file1.getIncludes(); for (IIndexInclude include : includes) { IIndexFileLocation target= include.getIncludesLocation(); Object key= target != null ? (Object) target : include.getFullName(); if (handled.add(key)) { result.add(include); if (nextLevel != null) { IIndexFile includedByFile= resolveInclude(include); if (includedByFile != null) { nextLevel.add(includedByFile); } } } } } if (nextLevel == null || nextLevel.isEmpty()) { break; } if (depth > 0) { depth--; } in = nextLevel; } return result.toArray(new IIndexInclude[result.size()]); } @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<>(); ILinkage[] linkages = Linkage.getIndexerLinkages(); SubMonitor loopMonitor = SubMonitor.convert(monitor, 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), loopMonitor.newChild(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<>(); 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<>(); 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<>(); 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<>(); 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<>(); HashSet<IIndexFileLocation> handledIFLs= new HashSet<>(); SubMonitor loopMonitor = SubMonitor.convert(monitor, Messages.CIndex_FindBindingsTask_label, fFragments.length); for (IIndexFragment fragment : fFragments) { HashSet<IIndexFile> allowedFiles= new HashSet<>(); try { IIndexMacro[] macros= fragment.findMacros(name, isPrefix, caseSensitive, filter, loopMonitor.newChild(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<>(); 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<>(); 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<>(); 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; } } }