Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;

import static org.junit.Assert.assertNotEquals;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -1576,6 +1578,109 @@ public void testUnrelatedTypedef_Bug214146() throws Exception {
}
}

// // h1.h
// typedef struct {
// int ts1;
// } ts;
//
// using tu = struct {
// int tu1;
// };
//
// struct A {
// int a1;
// };

// // h2.h
// typedef struct {
// int ts2;
// } ts;
//
// using tu = struct {
// int tu2;
// };
//
// struct A {
// int a2;
// };

// // s1.cpp
// #include "h1.h"
// int test1() {
// ts t;
// t.ts1 = 1;
// tu u;
// u.tu1 = 2;
// A a;
// a.a1 = 3;
// return u.u1 + a.a1;
// }

// // s2.cpp
// #include "h2.h"
// int test2() {
// ts t;
// t.ts2 = 4;
// tu u;
// u.tu2 = 5;
// A a;
// a.a2 = 6;
// return u.u2 + a.a2;
// }
public void testUnrelatedTypedefInHeader_Bug214146() throws Exception {
String[] contents = getContentsForTest(4);
final IIndexManager indexManager = CCorePlugin.getIndexManager();
IFile h1h = TestSourceReader.createFile(fCProject.getProject(), "h1.h", contents[0]);
IFile h2h = TestSourceReader.createFile(fCProject.getProject(), "h2.h", contents[1]);
IFile s1cpp = TestSourceReader.createFile(fCProject.getProject(), "s1.cpp", contents[2]);
IFile s2cpp = TestSourceReader.createFile(fCProject.getProject(), "s2.cpp", contents[3]);
indexManager.reindex(fCProject);
waitForIndexer();
fIndex.acquireReadLock();
try {
BindingAssertionHelper h1Helper = new BindingAssertionHelper(h1h, contents[0], fIndex);
ITypedef typedef1h = h1Helper.assertNonProblem("ts;", 2, ITypedef.class);
ITypedef alias1h = h1Helper.assertNonProblem("tu =", 2, ITypedef.class);
ICPPClassType class1h = h1Helper.assertNonProblem("A", 1, ICPPClassType.class);

BindingAssertionHelper h2Helper = new BindingAssertionHelper(h2h, contents[1], fIndex);
ITypedef typedef2h = h2Helper.assertNonProblem("ts;", 2, ITypedef.class);
ITypedef alias2h = h2Helper.assertNonProblem("tu =", 2, ITypedef.class);
ICPPClassType class2h = h2Helper.assertNonProblem("A", 1, ICPPClassType.class);

assertNotEquals(typedef1h, typedef2h);
assertNotEquals(alias1h, alias2h);
assertNotEquals(class1h, class2h);

BindingAssertionHelper s1Helper = new BindingAssertionHelper(s1cpp, contents[2], fIndex);
ITypedef typedef1binding = s1Helper.assertNonProblem("ts t;", 2, ITypedef.class);
s1Helper.assertNonProblem("ts1 = 1;", 3, ICPPVariable.class);
ITypedef alias1binding = s1Helper.assertNonProblem("tu u;", 2, ITypedef.class);
s1Helper.assertNonProblem("tu1 = 2;", 3, ICPPVariable.class);
ICPPClassType a1binding = s1Helper.assertNonProblem("A a;", 1, ICPPClassType.class);
s1Helper.assertNonProblem("a1 = 3;", 2, ICPPVariable.class);

BindingAssertionHelper s2Helper = new BindingAssertionHelper(s2cpp, contents[3], fIndex);
ITypedef typedef2binding = s2Helper.assertNonProblem("ts t;", 2, ITypedef.class);
s2Helper.assertNonProblem("ts2 = 4;", 3, ICPPVariable.class);
ITypedef alias2binding = s2Helper.assertNonProblem("tu u;", 2, ITypedef.class);
s2Helper.assertNonProblem("tu2 = 5;", 3, ICPPVariable.class);
ICPPClassType a2binding = s2Helper.assertNonProblem("A a;", 1, ICPPClassType.class);
s2Helper.assertNonProblem("a2 = 6;", 2, ICPPVariable.class);

// typedefs must be unique
assertNotEquals(typedef1binding, typedef2binding);

// aliases must be unique
assertNotEquals(alias1binding, alias2binding);

// class should be the same since CDT indexer adopts class redeclaration from different TU
assertEquals(a1binding, a2binding);
} finally {
fIndex.releaseReadLock();
}
}

// #undef BBB

// #define BBB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,12 @@ private static boolean isPartOfSource(IASTNode decl) {
}

private static IASTNode resolveConflict(IASTNode n1, IASTNode n2) {
if (n1 == null)
if (n1 == n2) {
// No need to dig deeper
return n1;
} else if (n1 == null) {
return n2;
}

IASTFileLocation loc1 = n1.getFileLocation();
if (loc1 == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ public IBinding[] getBindings(ScopeLookupData lookup) {
IBinding[] bindings = lookup.isPrefixLookup()
? index.findBindingsForContentAssist(nchars, true, filter, null)
: index.findBindings(nchars, filter, null);
if (fileSet != null) {
// if using promiscuous binding resolution, allow finding local bindings in index
// to help refactoring with typedefs and using declarations which are now local bindings
if (fileSet != null && !CPPSemantics.isUsingPromiscuousBindingResolution()) {
bindings = fileSet.filterFileLocalBindings(bindings);
}
result = ArrayUtil.addAll(IBinding.class, result, bindings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

import org.eclipse.cdt.core.CCorePlugin;
Expand All @@ -46,11 +48,13 @@
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.core.parser.util.ArrayUtil;
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.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
Expand Down Expand Up @@ -162,8 +166,67 @@ public IIndexBinding[] findMacroContainers(Pattern pattern, IndexFilter filter,
}
}

private static class BindingAndLocationComparator implements Comparator<IIndexName> {
@Override
public int compare(IIndexName f1, IIndexName f2) {
if (f1.equals(f2)) {
return 0;
}
try {
IIndexFile file1 = f1.getFile();
IIndexFile file2 = f2.getFile();
if (file1 != null && file2 != null) {
return file1.getLocation().getURI().compareTo(file2.getLocation().getURI());
}
} catch (CoreException e) {
}
return -1;
}
}

@Override
public IIndexName[] findNames(IBinding binding, int flags) throws CoreException {
ArrayList<IIndexName> result = new ArrayList<>();
PDOMNode pdomNode = binding.getAdapter(PDOMNode.class);
// collect names for this binding in all index fragments
if (!(SPECIALCASE_SINGLES && fFragments.length == 1)
&& pdomNode instanceof final IIndexFragmentBinding foreignIndexFragmeintBinding
&& foreignIndexFragmeintBinding.isFileLocal()) {
// same name in header file included from multiple projects will have multiple
// distinct fragment bindings private to index fragments belonging to projects

// 1. extract all fragment bindings with same name from all index fragments

ILinkage linkage = foreignIndexFragmeintBinding.getLinkage();
IIndexFragmentBinding[][] allBindings = findAllBindingsForLinkage(linkage, binding.getNameCharArray(),
false, IndexFilter.ALL, new NullProgressMonitor());

// 2. pick ones comparing equal to search argument and get names for each

ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
for (IIndexFragmentBinding[] parts : allBindings) {
if (parts == null) {
continue;
}
for (IIndexFragmentBinding part : parts) {
if (part == null) {
continue;
}
if (factory.compareCompositeBindings(foreignIndexFragmeintBinding, part) == 0) {
// found another fragment binding which looks like search argument
ArrayUtil.addAll(result, findNamesForBinding(part, flags));
}
}
}
} else {
ArrayUtil.addAll(result, findNamesForBinding(binding, flags));
}

// return all found names
return result.toArray(new IIndexName[result.size()]);
}

private IIndexName[] findNamesForBinding(IBinding binding, int flags) throws CoreException {
ArrayList<IIndexFragmentName> result = new ArrayList<>();
if (binding instanceof ICPPUsingDeclaration) {
IBinding[] bindings = ((ICPPUsingDeclaration) binding).getDelegates();
Expand Down Expand Up @@ -212,7 +275,16 @@ public IIndexName[] findNames(IBinding binding, int flags) throws CoreException

@Override
public IIndexName[] findDeclarations(IBinding binding) throws CoreException {
return findNames(binding, FIND_DECLARATIONS_DEFINITIONS);
IIndexName[] names = findNames(binding, FIND_DECLARATIONS_DEFINITIONS);

// callers expect single entry per file if it is included multiple times, deduplicate by file location

TreeSet<IIndexName> ts = new TreeSet<>(new BindingAndLocationComparator());
for (IIndexName name : names) {
ts.add(name);
}

return ts.toArray(new IIndexName[ts.size()]);
}

@Override
Expand Down Expand Up @@ -652,27 +724,35 @@ public IIndexBinding[] findBindings(char[] name, boolean filescope, IndexFilter
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));
}
IIndexFragmentBinding[][] fragmentBindings = findAllBindingsForLinkage(linkage, name, filescope, filter,
monitor);
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
return flatten(result);
}
}

private IIndexFragmentBinding[][] findAllBindingsForLinkage(ILinkage linkage, char[] name, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (!filter.acceptLinkage(linkage)) {
return new IIndexFragmentBinding[0][];
}

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;
}
}
return fragmentBindings;
}

@Override
public IIndexMacro[] findMacros(char[] name, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
return findMacros(name, false, true, filter, monitor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ protected IIndexFragmentBinding[] mergeBindingArrays(IIndexFragmentBinding[][] f
return ts.toArray(new IIndexFragmentBinding[ts.size()]);
}

@Override
public int compareCompositeBindings(IIndexFragmentBinding lhs, IIndexFragmentBinding rhs) {
return fragmentComparator.compare(lhs, rhs);
}

/**
* Convenience method for finding a binding with a definition (in the specified index
* context) which is equivalent to the specified binding. If no definition is found,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,12 @@ public interface ICompositesFactory {
* Converts values.
*/
public IValue getCompositeValue(IValue v);

/**
* Compares bindings
* @param lhs
* @param rhs
* @return
*/
public int compareCompositeBindings(IIndexFragmentBinding lhs, IIndexFragmentBinding rhs);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,11 @@ public IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) throws Co
return new PDOMInclude[0];
}

public boolean hasFileForLocation(int linkageId, IIndexFileLocation location) throws CoreException {
PDOMFile pdomFile = getFile(linkageId, location, null);
return pdomFile != null;
}

private PDOMFile adaptFile(IIndexFragmentFile file) throws CoreException {
if (file.getIndexFragment() == this && file instanceof PDOMFile) {
return (PDOMFile) file;
Expand Down Expand Up @@ -1410,14 +1415,17 @@ public IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, Inde
public IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, boolean isCaseSensitive,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
ArrayList<IIndexFragmentBinding> result = new ArrayList<>();
HashSet<PDOMBinding> uniqueNodes = new HashSet<>();
try {
for (PDOMLinkage linkage : getLinkageList()) {
if (filter.acceptLinkage(linkage)) {
if (isCaseSensitive) {
PDOMBinding[] bindings = linkage.getBindingsViaCache(name, monitor);
for (PDOMBinding binding : bindings) {
if (filter.acceptBinding(binding)) {
result.add(binding);
if (uniqueNodes.add(binding)) {
result.add(binding);
}
}
}
}
Expand All @@ -1438,7 +1446,9 @@ public IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, bool

PDOMBinding[] bindings = visitor.getBindings();
for (PDOMBinding binding : bindings) {
result.add(binding);
if (uniqueNodes.add(binding)) {
result.add(binding);
}
}
}
}
Expand Down
Loading
Loading