1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42: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:
Thomas Corbat 2017-01-03 16:30:54 +01:00 committed by Gerrit Code Review @ Eclipse.org
parent 903da92803
commit 5dff17514c
4 changed files with 184 additions and 80 deletions

View file

@ -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 |

View file

@ -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);
}
}
}
}

View file

@ -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;
}
}

View file

@ -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) {