mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 310837 - Indexer misses changes to header in referenced project
Extended PDOMManager to update index for header files in referencing projects Change-Id: I5a5b364651dbb854662c31197dd7ad77f13caff0 Signed-off-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
parent
903da92803
commit
5dff17514c
4 changed files with 184 additions and 80 deletions
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2013 Symbian Software Systems and others.
|
||||
* Copyright (c) 2007, 2017 Symbian Software Systems 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
|
||||
|
@ -13,15 +13,12 @@ package org.eclipse.cdt.internal.index.tests;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
|
@ -31,16 +28,12 @@ import org.eclipse.cdt.core.index.IIndex;
|
|||
import org.eclipse.cdt.core.index.IIndexManager;
|
||||
import org.eclipse.cdt.core.index.IndexFilter;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||
import org.eclipse.cdt.core.testplugin.CTestPlugin;
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IProjectDescription;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
|
@ -50,58 +43,6 @@ import junit.framework.Test;
|
|||
public class IndexCompositeTests extends BaseTestCase {
|
||||
Set<IProject> createdProjects = new HashSet<>();
|
||||
|
||||
/*
|
||||
* Convenience class for setting up projects.
|
||||
*/
|
||||
private class ProjectBuilder {
|
||||
private final String name;
|
||||
private final boolean cpp;
|
||||
private List<IProject> dependencies = new ArrayList<>();
|
||||
private Map<String, String> path2content = new HashMap<>();
|
||||
|
||||
ProjectBuilder(String name, boolean cpp) {
|
||||
this.name = name;
|
||||
this.cpp = cpp;
|
||||
}
|
||||
|
||||
ProjectBuilder addDependency(IProject project) {
|
||||
dependencies.add(project);
|
||||
return this;
|
||||
}
|
||||
|
||||
ProjectBuilder addFile(String relativePath, CharSequence content) {
|
||||
path2content.put(relativePath, content.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
ICProject create() throws Exception {
|
||||
ICProject result = cpp ?
|
||||
CProjectHelper.createCCProject(name, "bin", IPDOMManager.ID_NO_INDEXER) :
|
||||
CProjectHelper.createCProject(name, "bin", IPDOMManager.ID_NO_INDEXER);
|
||||
createdProjects.add(result.getProject());
|
||||
|
||||
IFile lastFile= null;
|
||||
for (Map.Entry<String, String> entry : path2content.entrySet()) {
|
||||
lastFile= TestSourceReader.createFile(result.getProject(), new Path(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
IProjectDescription desc = result.getProject().getDescription();
|
||||
desc.setReferencedProjects(dependencies.toArray(new IProject[dependencies.size()]));
|
||||
result.getProject().setDescription(desc, new NullProgressMonitor());
|
||||
|
||||
IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
indexManager.setIndexerId(result, IPDOMManager.ID_FAST_INDEXER);
|
||||
if (lastFile != null) {
|
||||
// Call reindex explicitly since setting indexer ID doesn't trigger reindexing.
|
||||
indexManager.reindex(result);
|
||||
IIndex index= indexManager.getIndex(result);
|
||||
TestSourceReader.waitUntilFileIsIndexed(index, lastFile, INDEXER_TIMEOUT_SEC * 1000);
|
||||
}
|
||||
BaseTestCase.waitForIndexer(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(IndexCompositeTests.class);
|
||||
}
|
||||
|
@ -128,6 +69,12 @@ public class IndexCompositeTests extends BaseTestCase {
|
|||
CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), blocks);
|
||||
}
|
||||
|
||||
protected ICProject createAndAddProject(ProjectBuilder builder) throws Exception {
|
||||
ICProject project = builder.create();
|
||||
createdProjects.add(project.getProject());
|
||||
return project;
|
||||
}
|
||||
|
||||
// class A {};
|
||||
|
||||
// class B {};
|
||||
|
@ -138,12 +85,12 @@ public class IndexCompositeTests extends BaseTestCase {
|
|||
try {
|
||||
ProjectBuilder pb = new ProjectBuilder("projB_" + getName(), true);
|
||||
pb.addFile("h1.h", contents[0]);
|
||||
ICProject cprojB = pb.create();
|
||||
ICProject cprojB = createAndAddProject(pb);
|
||||
projects.add(cprojB);
|
||||
|
||||
pb = new ProjectBuilder("projA_" + getName(), true);
|
||||
pb.addFile("h2.h", contents[1]).addDependency(cprojB.getProject());
|
||||
ICProject cprojA = pb.create();
|
||||
ICProject cprojA = createAndAddProject(pb);
|
||||
projects.add(cprojA);
|
||||
|
||||
setIndex(cprojB, NONE); assertBCount(1, 1);
|
||||
|
@ -186,17 +133,17 @@ public class IndexCompositeTests extends BaseTestCase {
|
|||
try {
|
||||
ProjectBuilder pb = new ProjectBuilder("projC_" + getName(), true);
|
||||
pb.addFile("h3.h", contents[0]);
|
||||
ICProject cprojC = pb.create();
|
||||
ICProject cprojC = createAndAddProject(pb);
|
||||
projects.add(cprojC);
|
||||
|
||||
pb = new ProjectBuilder("projB_" + getName(), true);
|
||||
pb.addFile("h2.h", contents[1]).addDependency(cprojC.getProject());
|
||||
ICProject cprojB = pb.create();
|
||||
ICProject cprojB = createAndAddProject(pb);
|
||||
projects.add(cprojB);
|
||||
|
||||
pb = new ProjectBuilder("projA_" + getName(), true);
|
||||
pb.addFile("h1.h", contents[2]).addDependency(cprojB.getProject());
|
||||
ICProject cprojA = pb.create();
|
||||
ICProject cprojA = createAndAddProject(pb);
|
||||
projects.add(cprojA);
|
||||
|
||||
/* Defines Global, Defines Namespace, References Global, References Namespace
|
||||
|
@ -301,17 +248,17 @@ public class IndexCompositeTests extends BaseTestCase {
|
|||
try {
|
||||
ProjectBuilder pb = new ProjectBuilder("projB_" + getName(), true);
|
||||
pb.addFile("h2.h", contents[0]);
|
||||
ICProject cprojB = pb.create();
|
||||
ICProject cprojB = createAndAddProject(pb);
|
||||
projects.add(cprojB);
|
||||
|
||||
pb = new ProjectBuilder("projA_" + getName(), true);
|
||||
pb.addFile("h1.h", contents[1]).addDependency(cprojB.getProject());
|
||||
ICProject cprojA = pb.create();
|
||||
ICProject cprojA = createAndAddProject(pb);
|
||||
projects.add(cprojA);
|
||||
|
||||
pb = new ProjectBuilder("projC_" + getName(), true);
|
||||
pb.addFile("h3.h", contents[2]).addDependency(cprojB.getProject());
|
||||
ICProject cprojC = pb.create();
|
||||
ICProject cprojC = createAndAddProject(pb);
|
||||
projects.add(cprojC);
|
||||
|
||||
/* A C |
|
||||
|
@ -399,17 +346,17 @@ public class IndexCompositeTests extends BaseTestCase {
|
|||
try {
|
||||
ProjectBuilder pb = new ProjectBuilder("projC_" + getName(), true);
|
||||
pb.addFile("h3.h", contents[0]);
|
||||
ICProject cprojC = pb.create();
|
||||
ICProject cprojC = createAndAddProject(pb);
|
||||
projects.add(cprojC);
|
||||
|
||||
pb = new ProjectBuilder("projA_" + getName(), true);
|
||||
pb.addFile("h1.h", contents[2]);
|
||||
ICProject cprojA = pb.create();
|
||||
ICProject cprojA = createAndAddProject(pb);
|
||||
projects.add(cprojA);
|
||||
|
||||
pb = new ProjectBuilder("projB_" + getName(), true);
|
||||
pb.addFile("h2.h", contents[1]).addDependency(cprojC.getProject()).addDependency(cprojA.getProject());
|
||||
ICProject cprojB = pb.create();
|
||||
ICProject cprojB = createAndAddProject(pb);
|
||||
projects.add(cprojB);
|
||||
|
||||
/* B |
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2015 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2007, 2017 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
|
||||
|
@ -10,7 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.index.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
|
@ -47,6 +49,7 @@ import org.eclipse.cdt.core.index.IIndex;
|
|||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IndexFilter;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.cdt.internal.core.pdom.CModelListener;
|
||||
|
@ -56,6 +59,7 @@ import org.eclipse.core.resources.IFile;
|
|||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
|
@ -1495,4 +1499,48 @@ public class IndexUpdateTests extends IndexTestBase {
|
|||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// int dummy;
|
||||
|
||||
//#include "A.h"
|
||||
//void foo() {
|
||||
// bar();
|
||||
//}
|
||||
public void testDependentProjectGetsUpdated_Bug310837() throws Exception {
|
||||
CharSequence[] contents = getContentsForTest(2);
|
||||
List<ICProject> projects = new ArrayList<ICProject>();
|
||||
|
||||
try {
|
||||
ProjectBuilder projectABuilder = new ProjectBuilder("projA_" + getName(), true);
|
||||
projectABuilder.addFile("A.h", contents[0]);
|
||||
ICProject projectA = projectABuilder.create();
|
||||
projects.add(projectA);
|
||||
|
||||
ProjectBuilder projectBBuilder = new ProjectBuilder("projB_" + getName(), true);
|
||||
projectBBuilder.addFile("B.h", contents[1]).addDependency(projectA.getProject());
|
||||
ICProject projectB = projectBBuilder.create();
|
||||
projects.add(projectB);
|
||||
|
||||
IIndex aIndex = CCorePlugin.getIndexManager().getIndex(projectA);
|
||||
IIndex bIndex = CCorePlugin.getIndexManager().getIndex(projectB);
|
||||
bIndex.acquireReadLock();
|
||||
IIndexBinding[] barBinding = bIndex.findBindings("bar".toCharArray(), IndexFilter.ALL, null);
|
||||
assertEquals(0, barBinding.length);
|
||||
bIndex.releaseReadLock();
|
||||
|
||||
IFile fileAh = (IFile) ((ITranslationUnit)projectA.findElement(Path.fromOSString("A.h"))).getResource();
|
||||
fileAh = TestSourceReader.createFile(projectA.getSourceRoots()[0].getResource(), Path.fromOSString("A.h"), "void bar(){}\n");
|
||||
TestSourceReader.waitUntilFileIsIndexed(aIndex, fileAh, INDEXER_TIMEOUT_SEC * 1000);
|
||||
TestSourceReader.waitUntilFileIsIndexed(bIndex, fileAh, INDEXER_TIMEOUT_SEC * 1000);
|
||||
bIndex.acquireReadLock();
|
||||
IIndexBinding[] barBinding2 = bIndex.findBindings("bar".toCharArray(), IndexFilter.ALL, null);
|
||||
assertEquals(1, barBinding2.length);
|
||||
bIndex.releaseReadLock();
|
||||
} finally {
|
||||
for (ICProject project : projects) {
|
||||
CProjectHelper.delete(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2017 Symbian Software Systems 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.index.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexManager;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IProjectDescription;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
/*
|
||||
* Convenience class for setting up projects.
|
||||
*/
|
||||
class ProjectBuilder {
|
||||
private final String name;
|
||||
private final boolean cpp;
|
||||
private List<IProject> dependencies = new ArrayList<>();
|
||||
private Map<String, String> path2content = new HashMap<>();
|
||||
|
||||
ProjectBuilder(String name, boolean cpp) {
|
||||
this.name = name;
|
||||
this.cpp = cpp;
|
||||
}
|
||||
|
||||
ProjectBuilder addDependency(IProject project) {
|
||||
dependencies.add(project);
|
||||
return this;
|
||||
}
|
||||
|
||||
ProjectBuilder addFile(String relativePath, CharSequence content) {
|
||||
path2content.put(relativePath, content.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
ICProject create() throws Exception {
|
||||
ICProject result = cpp ?
|
||||
CProjectHelper.createCCProject(name, "bin", IPDOMManager.ID_NO_INDEXER) :
|
||||
CProjectHelper.createCProject(name, "bin", IPDOMManager.ID_NO_INDEXER);
|
||||
|
||||
IFile lastFile= null;
|
||||
for (Map.Entry<String, String> entry : path2content.entrySet()) {
|
||||
lastFile= TestSourceReader.createFile(result.getProject(), new Path(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
IProjectDescription desc = result.getProject().getDescription();
|
||||
desc.setReferencedProjects(dependencies.toArray(new IProject[dependencies.size()]));
|
||||
result.getProject().setDescription(desc, new NullProgressMonitor());
|
||||
|
||||
IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
indexManager.setIndexerId(result, IPDOMManager.ID_FAST_INDEXER);
|
||||
if (lastFile != null) {
|
||||
// Call reindex explicitly since setting indexer ID doesn't trigger reindexing.
|
||||
indexManager.reindex(result);
|
||||
IIndex index= indexManager.getIndex(result);
|
||||
BaseTestCase.waitUntilFileIsIndexed(index, lastFile);
|
||||
}
|
||||
BaseTestCase.waitForIndexer(result);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2016 QNX Software Systems and others.
|
||||
* Copyright (c) 2005, 2017 QNX Software Systems 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
|
||||
|
@ -25,6 +25,7 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -797,24 +798,54 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
|||
}
|
||||
}
|
||||
|
||||
void changeProject(ICProject project, ITranslationUnit[] added, ITranslationUnit[] changed, ITranslationUnit[] removed) {
|
||||
assert !Thread.holdsLock(fProjectToPDOM);
|
||||
private void updateProject(ICProject project, ITranslationUnit[] added, ITranslationUnit[] changed,
|
||||
ITranslationUnit[] removed) {
|
||||
|
||||
IPDOMIndexer indexer = getIndexer(project);
|
||||
if (indexer != null && indexer.getID().equals(IPDOMManager.ID_NO_INDEXER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (fUpdatePolicies) {
|
||||
IndexUpdatePolicy policy = createPolicy(project);
|
||||
IPDOMIndexerTask task = policy.handleDelta(added, changed, removed);
|
||||
if (task != null) {
|
||||
enqueue(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void changeProject(ICProject project, ITranslationUnit[] added, ITranslationUnit[] changed,
|
||||
ITranslationUnit[] removed) {
|
||||
assert !Thread.holdsLock(fProjectToPDOM);
|
||||
if (added.length > 0 || changed.length > 0 || removed.length > 0) {
|
||||
synchronized (fUpdatePolicies) {
|
||||
IndexUpdatePolicy policy= createPolicy(project);
|
||||
IPDOMIndexerTask task= policy.handleDelta(added, changed, removed);
|
||||
if (task != null) {
|
||||
enqueue(task);
|
||||
updateProject(project, added, changed, removed);
|
||||
if (shouldUpdateReferencingProjects(added, changed, removed)) {
|
||||
ITranslationUnit[] addedHeaders = filterHeaderTU(added);
|
||||
ITranslationUnit[] changedHeaders = filterHeaderTU(changed);
|
||||
ITranslationUnit[] removedHeaders = filterHeaderTU(removed);
|
||||
IProject[] referencingProjects = project.getProject().getReferencingProjects();
|
||||
for (IProject referencingProject : referencingProjects) {
|
||||
ICProject projectToIndex = CoreModel.getDefault().create(referencingProject);
|
||||
updateProject(projectToIndex, addedHeaders, changedHeaders, removedHeaders);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ITranslationUnit[] filterHeaderTU(ITranslationUnit[] units) {
|
||||
return Arrays.stream(units).filter(ITranslationUnit::isHeaderUnit).toArray(ITranslationUnit[]::new);
|
||||
}
|
||||
|
||||
private boolean shouldUpdateReferencingProjects(ITranslationUnit[] added, ITranslationUnit[] changed,
|
||||
ITranslationUnit[] removed) {
|
||||
return hasHeaderTU(added) || hasHeaderTU(changed) || hasHeaderTU(removed);
|
||||
}
|
||||
|
||||
private boolean hasHeaderTU(ITranslationUnit[] units) {
|
||||
return Arrays.stream(units).anyMatch(ITranslationUnit::isHeaderUnit);
|
||||
}
|
||||
|
||||
private IndexUpdatePolicy createPolicy(final ICProject project) {
|
||||
assert !Thread.holdsLock(fProjectToPDOM);
|
||||
synchronized (fUpdatePolicies) {
|
||||
|
|
Loading…
Add table
Reference in a new issue