|
23 | 23 | import java.util.Arrays; |
24 | 24 | import java.util.Collection; |
25 | 25 | import java.util.Collections; |
| 26 | +import java.util.Comparator; |
26 | 27 | import java.util.HashMap; |
27 | 28 | import java.util.HashSet; |
28 | 29 | import java.util.List; |
29 | 30 | import java.util.Set; |
| 31 | +import java.util.TreeSet; |
30 | 32 | import java.util.regex.Pattern; |
31 | 33 |
|
32 | 34 | import org.eclipse.cdt.core.CCorePlugin; |
|
46 | 48 | import org.eclipse.cdt.core.index.IIndexName; |
47 | 49 | import org.eclipse.cdt.core.index.IndexFilter; |
48 | 50 | import org.eclipse.cdt.core.parser.ISignificantMacros; |
| 51 | +import org.eclipse.cdt.core.parser.util.ArrayUtil; |
49 | 52 | import org.eclipse.cdt.internal.core.dom.Linkage; |
50 | 53 | import org.eclipse.cdt.internal.core.index.composite.CompositingNotImplementedError; |
51 | 54 | import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; |
52 | 55 | import org.eclipse.cdt.internal.core.index.composite.c.CCompositesFactory; |
53 | 56 | import org.eclipse.cdt.internal.core.index.composite.cpp.CPPCompositesFactory; |
| 57 | +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; |
54 | 58 | import org.eclipse.core.runtime.CoreException; |
55 | 59 | import org.eclipse.core.runtime.IProgressMonitor; |
56 | 60 | import org.eclipse.core.runtime.NullProgressMonitor; |
@@ -162,8 +166,65 @@ public IIndexBinding[] findMacroContainers(Pattern pattern, IndexFilter filter, |
162 | 166 | } |
163 | 167 | } |
164 | 168 |
|
| 169 | + private static class BindingAndLocationComparator implements Comparator<IIndexName> { |
| 170 | + @Override |
| 171 | + public int compare(IIndexName f1, IIndexName f2) { |
| 172 | + if (f1.equals(f2)) { |
| 173 | + return 0; |
| 174 | + } |
| 175 | + try { |
| 176 | + IIndexFile file1 = f1.getFile(); |
| 177 | + IIndexFile file2 = f2.getFile(); |
| 178 | + if (file1 != null && file2 != null) { |
| 179 | + return file1.getLocation().getURI().compareTo(file2.getLocation().getURI()); |
| 180 | + } |
| 181 | + } catch (CoreException e) { |
| 182 | + } |
| 183 | + return -1; |
| 184 | + } |
| 185 | + } |
| 186 | + |
165 | 187 | @Override |
166 | 188 | public IIndexName[] findNames(IBinding binding, int flags) throws CoreException { |
| 189 | + ArrayList<IIndexName> result = new ArrayList<>(); |
| 190 | + PDOMNode pdomNode = binding.getAdapter(PDOMNode.class); |
| 191 | + if (pdomNode instanceof final IIndexFragmentBinding foreignIndexFragmeintBinding |
| 192 | + && foreignIndexFragmeintBinding.isFileLocal()) { |
| 193 | + // same name in header file included from multiple projects will have multiple |
| 194 | + // distinct fragment bindings private to index fragments belonging to projects |
| 195 | + |
| 196 | + // 1. extract all fragment bindings with same name from all index fragments |
| 197 | + |
| 198 | + ILinkage linkage = foreignIndexFragmeintBinding.getLinkage(); |
| 199 | + IIndexFragmentBinding[][] allBindings = findAllBindingsForLinkage(linkage, binding.getNameCharArray(), |
| 200 | + false, IndexFilter.ALL, new NullProgressMonitor()); |
| 201 | + |
| 202 | + // 2. pick ones comparing equal to search argument and get names for each |
| 203 | + |
| 204 | + ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID()); |
| 205 | + for (IIndexFragmentBinding[] parts : allBindings) { |
| 206 | + if (parts == null) { |
| 207 | + continue; |
| 208 | + } |
| 209 | + for (IIndexFragmentBinding part : parts) { |
| 210 | + if (part == null) { |
| 211 | + continue; |
| 212 | + } |
| 213 | + if (factory.compareCompositeBindings(foreignIndexFragmeintBinding, part) == 0) { |
| 214 | + // found another fragment binding which looks like search argument |
| 215 | + ArrayUtil.addAll(result, findNamesForBinding(part, flags)); |
| 216 | + } |
| 217 | + } |
| 218 | + } |
| 219 | + } else { |
| 220 | + ArrayUtil.addAll(result, findNamesForBinding(binding, flags)); |
| 221 | + } |
| 222 | + |
| 223 | + // return all found names |
| 224 | + return result.toArray(new IIndexName[result.size()]); |
| 225 | + } |
| 226 | + |
| 227 | + private IIndexName[] findNamesForBinding(IBinding binding, int flags) throws CoreException { |
167 | 228 | ArrayList<IIndexFragmentName> result = new ArrayList<>(); |
168 | 229 | if (binding instanceof ICPPUsingDeclaration) { |
169 | 230 | IBinding[] bindings = ((ICPPUsingDeclaration) binding).getDelegates(); |
@@ -212,7 +273,16 @@ public IIndexName[] findNames(IBinding binding, int flags) throws CoreException |
212 | 273 |
|
213 | 274 | @Override |
214 | 275 | public IIndexName[] findDeclarations(IBinding binding) throws CoreException { |
215 | | - return findNames(binding, FIND_DECLARATIONS_DEFINITIONS); |
| 276 | + IIndexName[] names = findNames(binding, FIND_DECLARATIONS_DEFINITIONS); |
| 277 | + |
| 278 | + // callers expect single entry per file if it is included multiple times, deduplicate by file location |
| 279 | + |
| 280 | + TreeSet<IIndexName> ts = new TreeSet<>(new BindingAndLocationComparator()); |
| 281 | + for (IIndexName name : names) { |
| 282 | + ts.add(name); |
| 283 | + } |
| 284 | + |
| 285 | + return ts.toArray(new IIndexName[ts.size()]); |
216 | 286 | } |
217 | 287 |
|
218 | 288 | @Override |
@@ -652,27 +722,35 @@ public IIndexBinding[] findBindings(char[] name, boolean filescope, IndexFilter |
652 | 722 | List<IIndexBinding[]> result = new ArrayList<>(); |
653 | 723 | ILinkage[] linkages = Linkage.getIndexerLinkages(); |
654 | 724 | for (ILinkage linkage : linkages) { |
655 | | - if (filter.acceptLinkage(linkage)) { |
656 | | - IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][]; |
657 | | - for (int i = 0; i < fFragments.length; i++) { |
658 | | - try { |
659 | | - IBinding[] part = fFragments[i].findBindings(name, filescope, |
660 | | - retargetFilter(linkage, filter), monitor); |
661 | | - fragmentBindings[i] = new IIndexFragmentBinding[part.length]; |
662 | | - System.arraycopy(part, 0, fragmentBindings[i], 0, part.length); |
663 | | - } catch (CoreException e) { |
664 | | - CCorePlugin.log(e); |
665 | | - fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; |
666 | | - } |
667 | | - } |
668 | | - ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID()); |
669 | | - result.add(factory.getCompositeBindings(fragmentBindings)); |
670 | | - } |
| 725 | + IIndexFragmentBinding[][] fragmentBindings = findAllBindingsForLinkage(linkage, name, filescope, filter, |
| 726 | + monitor); |
| 727 | + ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID()); |
| 728 | + result.add(factory.getCompositeBindings(fragmentBindings)); |
671 | 729 | } |
672 | 730 | return flatten(result); |
673 | 731 | } |
674 | 732 | } |
675 | 733 |
|
| 734 | + private IIndexFragmentBinding[][] findAllBindingsForLinkage(ILinkage linkage, char[] name, boolean filescope, |
| 735 | + IndexFilter filter, IProgressMonitor monitor) throws CoreException { |
| 736 | + if (!filter.acceptLinkage(linkage)) { |
| 737 | + return new IIndexFragmentBinding[0][]; |
| 738 | + } |
| 739 | + |
| 740 | + IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fFragments.length][]; |
| 741 | + for (int i = 0; i < fFragments.length; i++) { |
| 742 | + try { |
| 743 | + IBinding[] part = fFragments[i].findBindings(name, filescope, retargetFilter(linkage, filter), monitor); |
| 744 | + fragmentBindings[i] = new IIndexFragmentBinding[part.length]; |
| 745 | + System.arraycopy(part, 0, fragmentBindings[i], 0, part.length); |
| 746 | + } catch (CoreException e) { |
| 747 | + CCorePlugin.log(e); |
| 748 | + fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; |
| 749 | + } |
| 750 | + } |
| 751 | + return fragmentBindings; |
| 752 | + } |
| 753 | + |
676 | 754 | @Override |
677 | 755 | public IIndexMacro[] findMacros(char[] name, IndexFilter filter, IProgressMonitor monitor) throws CoreException { |
678 | 756 | return findMacros(name, false, true, filter, monitor); |
|
0 commit comments