From 33b684ca9144e03ae7c8ce5f4f28b1da29e48668 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 24 Jul 2003 14:15:07 +0000 Subject: [PATCH] Patch for Bogdan Gheorghe: - Here's a first take at the dependency tree service which is needed by both the managed build and the indexer. The service is in a really early form with no persistance or notification mechanisms in place yet. There is just enough in here to allow Sean to get his makefile dependencies. I added a check box to the indexer tab to enable the service on a per project basis. --- .../dependency/DepTest.cpp | 8 + .../dependency/DepTest.h | 8 + .../dependency/DepTest2.cpp | 8 + .../dependency/DepTest2.h | 8 + .../dependency/Inc1.h | 8 + .../org.eclipse.cdt.core.tests/dependency/a.h | 8 + .../org.eclipse.cdt.core.tests/dependency/c.h | 6 + .../org.eclipse.cdt.core.tests/dependency/d.h | 6 + .../core/indexer/tests/IndexManagerTests.java | 85 +++- core/org.eclipse.cdt.core/.classpath | 1 + .../build/managed/ManagedBuildManager.java | 2 +- .../org.eclipse.cdt.core/dependency/ChangeLog | 23 ++ .../AddFileToDependencyTree.java | 112 +++++ .../sourcedependency/DependencyManager.java | 384 ++++++++++++++++++ .../sourcedependency/DependencyQueryJob.java | 64 +++ .../sourcedependency/DependencyRequest.java | 64 +++ .../sourcedependency/DependencyRequestor.java | 60 +++ .../core/sourcedependency/DependencyTree.java | 174 ++++++++ .../EntireProjectDependencyTree.java | 192 +++++++++ .../sourcedependency/IDependencyTree.java | 82 ++++ .../sourcedependency/IPreprocessorOutput.java | 20 + .../sourcedependency/ISourceDependency.java | 19 + .../sourcedependency/PreprocessorOutput.java | 58 +++ .../sourcedependency/impl/InMemoryTree.java | 143 +++++++ .../sourcedependency/impl/IncludeEntry.java | 159 ++++++++ .../impl/IncludeEntryHashedArray.java | 84 ++++ .../core/sourcedependency/impl/Node.java | 45 ++ .../org/eclipse/cdt/core/model/CoreModel.java | 8 + .../internal/core/model/CModelManager.java | 5 + .../internal/core/model/DeltaProcessor.java | 5 +- .../src/org/eclipse/cdt/core/CCorePlugin.java | 3 + core/org.eclipse.cdt.ui/ChangeLog | 4 + .../eclipse/cdt/ui/wizards/IndexerBlock.java | 19 +- 33 files changed, 1869 insertions(+), 6 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/dependency/DepTest.cpp create mode 100644 core/org.eclipse.cdt.core.tests/dependency/DepTest.h create mode 100644 core/org.eclipse.cdt.core.tests/dependency/DepTest2.cpp create mode 100644 core/org.eclipse.cdt.core.tests/dependency/DepTest2.h create mode 100644 core/org.eclipse.cdt.core.tests/dependency/Inc1.h create mode 100644 core/org.eclipse.cdt.core.tests/dependency/a.h create mode 100644 core/org.eclipse.cdt.core.tests/dependency/c.h create mode 100644 core/org.eclipse.cdt.core.tests/dependency/d.h create mode 100644 core/org.eclipse.cdt.core/dependency/ChangeLog create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyQueryJob.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyRequest.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyRequestor.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyTree.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IDependencyTree.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IPreprocessorOutput.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/ISourceDependency.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/PreprocessorOutput.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/InMemoryTree.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java create mode 100644 core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/Node.java diff --git a/core/org.eclipse.cdt.core.tests/dependency/DepTest.cpp b/core/org.eclipse.cdt.core.tests/dependency/DepTest.cpp new file mode 100644 index 00000000000..828a3aca6cf --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/DepTest.cpp @@ -0,0 +1,8 @@ +#include "DepTest.h" +#include "d.h" + +DepTest::DepTest() +{}; +DepTest::~DepTest() +{}; + diff --git a/core/org.eclipse.cdt.core.tests/dependency/DepTest.h b/core/org.eclipse.cdt.core.tests/dependency/DepTest.h new file mode 100644 index 00000000000..c008086c156 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/DepTest.h @@ -0,0 +1,8 @@ +#include "Inc1.h" +#include "a.h" +class DepTest{ +public: + + DepTest(); + ~DepTest(); +}; diff --git a/core/org.eclipse.cdt.core.tests/dependency/DepTest2.cpp b/core/org.eclipse.cdt.core.tests/dependency/DepTest2.cpp new file mode 100644 index 00000000000..6f3000e6df3 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/DepTest2.cpp @@ -0,0 +1,8 @@ +#include "DepTest2.h" +#include "d.h" + +DepTest2::DepTest2() +{}; +DepTest2::~DepTest2() +{}; + diff --git a/core/org.eclipse.cdt.core.tests/dependency/DepTest2.h b/core/org.eclipse.cdt.core.tests/dependency/DepTest2.h new file mode 100644 index 00000000000..6f084a69b11 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/DepTest2.h @@ -0,0 +1,8 @@ +#include "d.h" + +class DepTest2{ +public: + + DepTest2(); + ~DepTest2(); +}; diff --git a/core/org.eclipse.cdt.core.tests/dependency/Inc1.h b/core/org.eclipse.cdt.core.tests/dependency/Inc1.h new file mode 100644 index 00000000000..7bfbe592caa --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/Inc1.h @@ -0,0 +1,8 @@ +#include "c.h" + +class X +{ + public: + X(){}; + ~X(){}; +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/dependency/a.h b/core/org.eclipse.cdt.core.tests/dependency/a.h new file mode 100644 index 00000000000..3c66f940fc1 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/a.h @@ -0,0 +1,8 @@ +#include "c.h" + +class Z +{ + public: + Z(){}; + ~Z(){}; +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/dependency/c.h b/core/org.eclipse.cdt.core.tests/dependency/c.h new file mode 100644 index 00000000000..bc82542a695 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/c.h @@ -0,0 +1,6 @@ +class Y +{ + public: + Y(){}; + ~Y(){}; +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/dependency/d.h b/core/org.eclipse.cdt.core.tests/dependency/d.h new file mode 100644 index 00000000000..8dcf01a87d2 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/dependency/d.h @@ -0,0 +1,6 @@ +class d +{ + public: + d(){}; + ~d(){}; +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/indexer/org/eclipse/cdt/core/indexer/tests/IndexManagerTests.java b/core/org.eclipse.cdt.core.tests/indexer/org/eclipse/cdt/core/indexer/tests/IndexManagerTests.java index cd2471e398a..dce0bc4d0a5 100644 --- a/core/org.eclipse.cdt.core.tests/indexer/org/eclipse/cdt/core/indexer/tests/IndexManagerTests.java +++ b/core/org.eclipse.cdt.core.tests/indexer/org/eclipse/cdt/core/indexer/tests/IndexManagerTests.java @@ -11,18 +11,23 @@ package org.eclipse.cdt.core.indexer.tests; import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Iterator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.search.ICSearchConstants; import org.eclipse.cdt.internal.core.index.IEntryResult; import org.eclipse.cdt.internal.core.index.IIndex; import org.eclipse.cdt.internal.core.index.IQueryResult; import org.eclipse.cdt.internal.core.index.impl.IFileDocument; import org.eclipse.cdt.internal.core.search.indexing.IIndexConstants; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyQueryJob; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; @@ -80,7 +85,7 @@ public class IndexManagerTests extends TestCase { public static Test suite() { //TestSuite suite = new TestSuite(); - //suite.addTest(new IndexManagerTests("testIndexContents")); + //suite.addTest(new IndexManagerTests("testDependencyTree")); //return suite; return new TestSuite(IndexManagerTests.class); } @@ -114,7 +119,7 @@ public class IndexManagerTests extends TestCase { return cproject; } - private void importFile(String fileName, String resourceLocation)throws Exception{ + private IFile importFile(String fileName, String resourceLocation)throws Exception{ //Obtain file handle file = testProject.getProject().getFile(fileName); String pluginRoot=org.eclipse.core.runtime.Platform.getPlugin("org.eclipse.cdt.core.tests").find(new Path("/")).getFile(); @@ -124,6 +129,7 @@ public class IndexManagerTests extends TestCase { file.create(new FileInputStream(pluginRoot + resourceLocation),false,monitor); } fileDoc = new IFileDocument(file); + return file; } private void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException { @@ -342,4 +348,79 @@ public class IndexManagerTests extends TestCase { assertEquals(methodResultModel[i],methodresults[i].toString()); } } + + public void testDependencyTree() throws Exception{ + //Add a file to the project + IFile depTest = importFile("DepTest.cpp","resources/dependency/DepTest.cpp"); + importFile("DepTest.h","resources/dependency/DepTest.h"); + importFile("a.h","resources/dependency/a.h"); + importFile("c.h","resources/dependency/c.h"); + importFile("d.h","resources/dependency/d.h"); + importFile("Inc1.h","resources/dependency/Inc1.h"); + importFile("DepTest2.h","resources/dependency/DepTest2.h"); + IFile depTest2 = importFile("DepTest2.cpp","resources/dependency/DepTest2.cpp"); + //Enable indexing on the created project + //By doing this, we force the Dependency Manager to do a g() + DependencyManager dependencyManager = CCorePlugin.getDefault().getCoreModel().getDependencyManager(); + dependencyManager.setEnabled(testProject,true); + Thread.sleep(10000); + String[] depTestModel = {"\\IndexerTestProject\\d.h", "\\IndexerTestProject\\Inc1.h", "\\IndexerTestProject\\c.h", "\\IndexerTestProject\\a.h", "\\IndexerTestProject\\DepTest.h"}; + String[] depTest2Model = {"\\IndexerTestProject\\d.h", "\\IndexerTestProject\\DepTest2.h"}; + + ArrayList includes = new ArrayList(); + dependencyManager.performConcurrentJob(new DependencyQueryJob(testProject,depTest,dependencyManager,includes),ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,null); + //Thread.sleep(5000); + String[] depTestModelLocal = convertToLocalPath(depTestModel); + String[] depTestIncludes = new String[includes.size()]; + Iterator includesIterator = includes.iterator(); + int i=0; + while(includesIterator.hasNext()){ + depTestIncludes[i] = (String) includesIterator.next(); + i++; + } + + if (depTestModelLocal.length != depTestIncludes.length) + fail("Number of included files differsfrom model"); + + for (i=0;i + diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java index fe6443a2593..54d2e7920e4 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java @@ -420,7 +420,7 @@ public class ManagedBuildManager implements IScannerInfoProvider { * @param resource * @return */ - private static IScannerInfo getScannerInfo(IResource resource) { + public static IScannerInfo getScannerInfo(IResource resource) { return (IScannerInfo) getBuildInfo(resource, false); } diff --git a/core/org.eclipse.cdt.core/dependency/ChangeLog b/core/org.eclipse.cdt.core/dependency/ChangeLog new file mode 100644 index 00000000000..92d447382c3 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/ChangeLog @@ -0,0 +1,23 @@ +2003-07-23 Bogdan Gheorghe + + Added initial dependency implementation + + * src/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java + * src/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java + * src/org/eclipse/cdt/internal/core/sourcedependency/DenpendencyQueryJob.java + * src/org/eclipse/cdt/internal/core/sourcedependency/DependencyRequest.java + * src/org/eclipse/cdt/internal/core/sourcedependency/DependencyRequestor.java + * src/org/eclipse/cdt/internal/core/sourcedependency/DependencyTree.java + * src/org/eclipse/cdt/internal/core/sourcedependency/EntireProjectDependencyTree.java + * src/org/eclipse/cdt/internal/core/sourcedependency/IDependencyTree.java + * src/org/eclipse/cdt/internal/core/sourcedependency/IPreprocessorOutput.java + * src/org/eclipse/cdt/internal/core/sourcedependency/ISourceDependency.java + * src/org/eclipse/cdt/internal/core/sourcedependency/PreprocessorOutput.java + + * src/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java + * src/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java + * src/org/eclipse/cdt/internal/core/sourcedependency/impl/InMemoryTree.java + * src/org/eclipse/cdt/internal/core/sourcedependency/impl/Node.java + + + \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java new file mode 100644 index 00000000000..62ed9301ab4 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/AddFileToDependencyTree.java @@ -0,0 +1,112 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; + +import java.io.IOException; + +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.internal.core.index.IDocument; +import org.eclipse.cdt.internal.core.index.impl.IFileDocument; +import org.eclipse.cdt.internal.core.parser.ScannerInfo; +import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor; +import org.eclipse.cdt.internal.core.search.processing.JobManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +public class AddFileToDependencyTree extends DependencyRequest { + public static final String[] FILE_TYPES= new String[] {"cpp"}; //$NON-NLS-1$ + + IFile resource; + char[] contents; + IScannerInfo buildInfo; + + /** + * @param path + * @param manager + */ + public AddFileToDependencyTree( + IFile resource, + IPath path, + DependencyManager manager, + IScannerInfo info) { + super(path, manager); + this.resource = resource; + this.buildInfo = info; + } + + public boolean execute(IProgressMonitor progressMonitor) { + if (progressMonitor != null && progressMonitor.isCanceled()) return true; + /* ensure no concurrent write access to tree */ + IDependencyTree tree = manager.getDependencyTree(this.dependencyTreePath, true, /*reuse tree file*/ true /*create if none*/); + if (tree == null) return true; + ReadWriteMonitor monitor = manager.getMonitorFor(tree); + if (monitor == null) return true; // tree got deleted since acquired + try { + monitor.enterWrite(); // ask permission to write + if (!addDocumentToTree(tree)) return false; + } catch (IOException e) { + if (JobManager.VERBOSE) { + JobManager.verbose("-> failed to calculate dependency for " + this.resource + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$ + e.printStackTrace(); + } + return false; + } finally { + monitor.exitWrite(); // free write lock + } + return true; + } + + protected boolean addDocumentToTree(IDependencyTree dTree) throws IOException { + if (!initializeContents()) return false; + //Need to create document to get string content... + IDocument document = new IFileDocument(resource, this.contents); + if (!shouldAddToTree(document)) return false; + + String docPath = resource.getLocation().toOSString(); + IScannerInfo newInfo = new ScannerInfo((this.buildInfo != null) ? this.buildInfo.getDefinedSymbols() : null,(this.buildInfo != null) ? this.buildInfo.getIncludePaths() : null); + + dTree.add(document,docPath,newInfo); + return true; + } + + public boolean initializeContents() { + if (this.contents == null) { + try { + IPath location = resource.getLocation(); + if (location != null) + this.contents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(location.toFile(), null); + } catch (IOException e) { + } + } + return this.contents != null; + } + + public String toString() { + return "calculating dependency for: " + this.resource.getFullPath(); //$NON-NLS-1$ + } + + public String[] getFileTypes(){ + return FILE_TYPES; + } + + public boolean shouldAddToTree(IDocument document) { + String type = document.getType(); + String[] supportedTypes = this.getFileTypes(); + for (int i = 0; i < supportedTypes.length; ++i) { + if (supportedTypes[i].equals(type)) + return true; + } + return false; + } + +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java new file mode 100644 index 00000000000..50cded45c14 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyManager.java @@ -0,0 +1,384 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.CRC32; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.internal.core.search.CharOperation; +import org.eclipse.cdt.internal.core.search.SimpleLookupTable; +import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor; +import org.eclipse.cdt.internal.core.search.processing.JobManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.QualifiedName; + +/** + * @author bgheorgh + */ +public class DependencyManager extends JobManager implements ISourceDependency { + /* number of file contents in memory */ + public static int MAX_FILES_IN_MEMORY = 0; + + public SimpleLookupTable projectNames = new SimpleLookupTable(); + private Map dependencyTrees = new HashMap(5); + + /* read write monitors */ + private Map monitors = new HashMap(5); + + /* need to save ? */ + private boolean needToSave = false; + private static final CRC32 checksumCalculator = new CRC32(); + private IPath ccorePluginLocation = null; + + /* can only replace a current state if its less than the new one */ + private SimpleLookupTable dTreeStates = null; + private File savedDTreesFile = + new File(getCCorePluginWorkingLocation().append("savedDTrees.txt").toOSString()); //$NON-NLS-1$ + public static Integer SAVED_STATE = new Integer(0); + public static Integer UPDATING_STATE = new Integer(1); + public static Integer UNKNOWN_STATE = new Integer(2); + public static Integer REBUILDING_STATE = new Integer(3); + + public String processName(){ + //TODO: BOG Add name to .properties file + return "Dependency Tree"; //org.eclipse.cdt.internal.core.search.Util.bind("process.name"); //$NON-NLS-1$ + } + + public void reset(){ + super.reset(); + + //Get handles on the info providers + //register yourself for updates + + if (this.dependencyTrees!= null) { + this.dependencyTrees = new HashMap(5); + this.monitors = new HashMap(5); + this.dTreeStates = null; + } + + this.projectNames = new SimpleLookupTable(); + this.ccorePluginLocation = null; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.ISourceDependency#getProjects(org.eclipse.core.resources.IFile) + */ + public IProject[] getProjects(IFile file) { + // TODO Auto-generated method stub + return null; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.ISourceDependency#getFileDependencies(org.eclipse.core.resources.IProject, org.eclipse.core.resources.IFile) + */ + public synchronized String[] getFileDependencies(IProject project, IFile file) { + IPath path =project.getFullPath(); + IDependencyTree dTree= this.getDependencyTree(path,true,false); + try{ + //dTree.printIncludeEntries(); + //dTree.printIndexedFiles(); + String[] files = dTree.getFileDependencies(file.getFullPath()); + return files; + } + catch(Exception e){} + return null; + } + + public synchronized IDependencyTree getDependencyTree(IPath path, boolean reuseExistingFile, boolean createIfMissing) { + IDependencyTree dTree = (IDependencyTree) dependencyTrees.get(path); + if (dTree == null){ + String treeName = computeTreeName(path); + Object state = getTreeStates().get(treeName); + Integer currentDTreeState = state == null ? UNKNOWN_STATE : (Integer) state; + if (currentDTreeState == UNKNOWN_STATE) { + // should only be reachable for query jobs + rebuildDTree(treeName, path); + return null; + } + // tree isn't cached, consider reusing an existing tree file + if (reuseExistingFile) { + File treeFile = new File(treeName); + if (treeFile.exists()) { // check before creating tree so as to avoid creating a new empty tree if file is missing + try { + dTree = new DependencyTree(treeName, "Tree for " + path.toOSString(), true /*reuse tree file*/); //$NON-NLS-1$ + dependencyTrees.put(path, dTree); + monitors.put(dTree, new ReadWriteMonitor()); + return dTree; + } catch (IOException e) { + // failed to read the existing file or its no longer compatible + if (currentDTreeState != REBUILDING_STATE) { // rebuild tree if existing file is corrupt, unless the tree is already being rebuilt + if (VERBOSE) + JobManager.verbose("-> cannot reuse existing tree: "+ treeName +" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ + rebuildDTree(treeName, path); + return null; + } else { + dTree = null; // will fall thru to createIfMissing & create a empty tree for the rebuild all job to populate + } + } + } + if (currentDTreeState == SAVED_STATE) { // rebuild tree if existing file is missing + rebuildDTree(treeName, path); + return null; + } + + if (createIfMissing) { + try { + if (VERBOSE) + JobManager.verbose("-> create empty tree: "+treeName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ + dTree = new DependencyTree(treeName, "Tree for " + path.toOSString(), false /*do not reuse tree file*/); //$NON-NLS-1$ + dependencyTrees.put(path, dTree); + monitors.put(dTree, new ReadWriteMonitor()); + return dTree; + } catch (IOException e) { + if (VERBOSE) + JobManager.verbose("-> unable to create empty tree: "+treeName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ + // The file could not be created. Possible reason: the project has been deleted. + return null; + } + } + } + } + + return dTree; + } + + String computeTreeName(IPath path) { + String name = (String) projectNames.get(path); + if (name == null) { + String pathString = path.toOSString(); + checksumCalculator.reset(); + checksumCalculator.update(pathString.getBytes()); + String fileName = Long.toString(checksumCalculator.getValue()) + ".depTree"; //$NON-NLS-1$ + if (VERBOSE) + JobManager.verbose("-> dependency tree name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$ + name = getCCorePluginWorkingLocation().append(fileName).toOSString(); + projectNames.put(path, name); + } + return name; + } + + private IPath getCCorePluginWorkingLocation() { + if (this.ccorePluginLocation != null) return this.ccorePluginLocation; + + return this.ccorePluginLocation = CCorePlugin.getDefault().getStateLocation(); + } + /** + * DTree access is controlled through a read-write monitor so as + * to ensure there is no concurrent read and write operations + * (only concurrent reading is allowed). + */ + public ReadWriteMonitor getMonitorFor(IDependencyTree dTree){ + return (ReadWriteMonitor) monitors.get(dTree); + } + + private SimpleLookupTable getTreeStates() { + if (dTreeStates != null) return dTreeStates; + + this.dTreeStates = new SimpleLookupTable(); + char[] savedDTreeNames = readDTreeState(); + if (savedDTreeNames.length > 0) { + char[][] names = CharOperation.splitOn('\n', savedDTreeNames); + for (int i = 0, l = names.length; i < l; i++) { + char[] name = names[i]; + if (name.length > 0) + this.dTreeStates.put(new String(name), SAVED_STATE); + } + } + return this.dTreeStates; + } + + private char[] readDTreeState() { + try { + return org.eclipse.cdt.internal.core.search.Util.getFileCharContent(savedDTreesFile, null); + } catch (IOException ignored) { + if (VERBOSE) + JobManager.verbose("Failed to read saved dTree file names"); //$NON-NLS-1$ + return new char[0]; + } + } + + private void rebuildDTree(String treeName, IPath path) { + Object target = org.eclipse.cdt.internal.core.search.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true); + if (target == null) return; + + if (VERBOSE) + JobManager.verbose("-> request to rebuild dTree: "+treeName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ + + updateTreeState(treeName, REBUILDING_STATE); + DependencyRequest request = null; + if (target instanceof IProject) { + IProject p = (IProject) target; + request = new EntireProjectDependencyTree(p, this); + } + + if (request != null) + request(request); + } + /** + * Trigger addition of the entire content of a project + * Note: the actual operation is performed in background + */ + public void generateEntireDependencyTree(IProject project) { + if (CCorePlugin.getDefault() == null) return; + + /****** + *TODO: Remove these methods once the depTree is + *fully integrated + */ + if (!isEnabled(project)) return; + + // check if the same request is not already in the queue + DependencyRequest request = new EntireProjectDependencyTree(project, this); + for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488) + if (request.equals(this.awaitingJobs[i])) return; + this.request(request); + } + + private void updateTreeState(String treeName, Integer treeState) { + getTreeStates(); // ensure the states are initialized + if (treeState != null) { + if (treeState.equals(dTreeStates.get(treeName))) return; // not changed + dTreeStates.put(treeName, treeState); + } else { + if (!dTreeStates.containsKey(treeName)) return; // did not exist anyway + dTreeStates.removeKey(treeName); + } + + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(savedDTreesFile)); + Object[] indexNames = dTreeStates.keyTable; + Object[] states = dTreeStates.valueTable; + for (int i = 0, l = states.length; i < l; i++) { + if (states[i] == SAVED_STATE) { + writer.write((String) indexNames[i]); + writer.write('\n'); + } + } + } catch (IOException ignored) { + if (VERBOSE) + JobManager.verbose("Failed to write saved dTree file names"); //$NON-NLS-1$ + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) {} + } + } + if (VERBOSE) { + String state = "?"; //$NON-NLS-1$ + if (treeState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$ + else if (treeState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$ + else if (treeState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$ + else if (treeState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$ + JobManager.verbose("-> dTree state updated to: " + state + " for: "+treeName); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + public void jobWasCancelled(IPath path) { + Object o = this.dependencyTrees.get(path); + if (o instanceof IDependencyTree) { + this.monitors.remove(o); + this.dependencyTrees.remove(path); + } + updateTreeState(computeTreeName(path), UNKNOWN_STATE); + } + /** + * Trigger removal of a resource from a tree + * Note: the actual operation is performed in background + */ + public void remove(String resourceName, IPath indexedContainer){ + //request(new RemoveFromIndex(resourceName, indexedContainer, this)); + } + /** + * Removes the tree for a given path. + * This is a no-op if the tree did not exist. + */ + public synchronized void removeTree(IPath path) { + if (VERBOSE) + JobManager.verbose("removing dependency tree " + path); //$NON-NLS-1$ + String treeName = computeTreeName(path); + File indexFile = new File(treeName); + if (indexFile.exists()) + indexFile.delete(); + Object o = this.dependencyTrees.get(path); + if (o instanceof IDependencyTree) + this.monitors.remove(o); + this.dependencyTrees.remove(path); + updateTreeState(treeName, null); + } + /************* + *TODO: Remove these methods once the depTree is + *fully integrated + * START OF TEMP D-TREE ENABLE SECTION + */ + final static String DEP_MODEL_ID = CCorePlugin.PLUGIN_ID + ".dependencytree"; + final static String ACTIVATION = "enable"; + + static QualifiedName activationKey = new QualifiedName(DEP_MODEL_ID, ACTIVATION); + + public boolean isEnabled(IProject project) { + String prop = null; + try { + if (project != null) { + prop = project.getPersistentProperty(activationKey); + } + } catch (CoreException e) { + } + return ((prop != null) && prop.equalsIgnoreCase("true")); + } + + public void setEnabled(IProject project, boolean on) { + try { + if (project != null) { + Boolean newValue = new Boolean(on); + Boolean oldValue = new Boolean(isEnabled(project)); + if (!oldValue.equals(newValue)) { + project.setPersistentProperty(activationKey, newValue.toString()); + if (on) { + generateEntireDependencyTree(project); + } else { + //remove(project); + } + } + } + } catch (CoreException e) { + } + } + /** + * @param file + * @param path + * @param info + */ + public void addSource(IFile file, IPath path, IScannerInfo info) { + if (CCorePlugin.getDefault() == null) return; + AddFileToDependencyTree job = new AddFileToDependencyTree(file, path, this, info); + if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) { + // reduces the chance that the file is open later on, preventing it from being deleted + if (!job.initializeContents()) return; + } + request(job); + } + + /************ + * END OF TEMP D-TREE ENABLE SECTION + */ +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyQueryJob.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyQueryJob.java new file mode 100644 index 00000000000..628648e95a6 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyQueryJob.java @@ -0,0 +1,64 @@ +/* + * Created on Jul 23, 2003 + */ +package org.eclipse.cdt.internal.core.sourcedependency; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.internal.core.search.processing.IJob; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * @author bgheorgh + */ +public class DependencyQueryJob implements IJob { + + IProject project; + IFile file; + ArrayList includeFiles; + DependencyManager depManager; + + public DependencyQueryJob(IProject project, IFile file, DependencyManager depMan, List includeFiles) { + this.project = project; + this.file = file; + this.depManager = depMan; + this.includeFiles = (ArrayList) includeFiles; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.search.processing.IJob#belongsTo(java.lang.String) + */ + public boolean belongsTo(String jobFamily) { + // TODO Auto-generated method stub + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.search.processing.IJob#cancel() + */ + public void cancel() {} + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.search.processing.IJob#execute(org.eclipse.core.runtime.IProgressMonitor) + */ + public boolean execute(IProgressMonitor progress) { + + String[] tempFiles = this.depManager.getFileDependencies(project,file); + for (int i=0; i 0 ) ? (IASTInclusion) includeStack.removeFirst() : null; + return oldInclude; + } + + private IASTInclusion peekInclude(){ + return currentInclude; + } +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyTree.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyTree.java new file mode 100644 index 00000000000..c3fcec3f6bb --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/DependencyTree.java @@ -0,0 +1,174 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.parser.IPreprocessor; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.internal.core.index.IDocument; +import org.eclipse.cdt.internal.core.index.IQueryResult; +import org.eclipse.cdt.internal.core.index.impl.IndexedFile; +import org.eclipse.cdt.internal.core.sourcedependency.impl.InMemoryTree; +import org.eclipse.cdt.internal.core.sourcedependency.impl.IncludeEntry; +import org.eclipse.core.runtime.IPath; + + +public class DependencyTree implements IDependencyTree { + + protected InMemoryTree addsTree; + + public DependencyTree(String treeName, String string, boolean b) throws IOException{ + initialize(); + } + + public DependencyTree() throws IOException { + initialize(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#empty() + */ + public void empty() throws IOException { + // TODO Auto-generated method stub + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#getIndexFile() + */ + public File getIndexFile() { + // TODO Auto-generated method stub + return null; + } + /** + * Returns the number of referencing files in this tree. + */ + public int getNumDocuments() throws IOException { + return addsTree.getNumFiles(); + } + /** + * Returns the number of include entries in this tree. + * @return + * @throws IOException + */ + public int getNumIncludes() throws IOException { + return addsTree.getNumIncludes(); + } + /** + * Returns the path corresponding to a given document number + */ + public String getPath(int documentNumber) throws IOException { + return null; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#hasChanged() + */ + public boolean hasChanged() { + // TODO Auto-generated method stub + return false; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#query(java.lang.String) + */ + public IQueryResult[] query(String word) throws IOException { + // TODO Auto-generated method stub + return null; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#queryInDocumentNames(java.lang.String) + */ + public IQueryResult[] queryInDocumentNames(String word) + throws IOException { + // TODO Auto-generated method stub + return null; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#save() + */ + public void save() throws IOException { + // TODO Auto-generated method stub + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#remove(java.lang.String) + */ + public void remove(String documentName) throws IOException { + // TODO Auto-generated method stub + } + /** + * Add the file that will be preprocessed to the tree, create a new + * preprocessor output and preprocess! + */ + public void add(IDocument document, String docPath, IScannerInfo newInfo) throws IOException { + IndexedFile indexedFile= addsTree.getIndexedFile(document.getName()); + //if (indexedFile != null) + //remove(indexedFile, 0); + PreprocessorOutput output= new PreprocessorOutput(addsTree); + DependencyRequestor depReq = new DependencyRequestor(output,document); + + output.addDocument(document); + + IPreprocessor preprocessor = ParserFactory.createPreprocessor( new StringReader( document.getStringContent() ),docPath , newInfo, ParserMode.COMPLETE_PARSE,depReq); + preprocessor.process(); + } + /** + * Initialises the indexGenerator. + */ + public void initialize() throws IOException { + //initialisation of addsTree + addsTree= new InMemoryTree(); + } + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.sourcedependency.IDependencyTree#getFileDepencies(int) + */ + public String[] getFileDependencies(IPath filePath) throws IOException { + List tempFileReturn = new ArrayList(); + IndexedFile indexFile = addsTree.getIndexedFile(filePath.toString()); + int fileNum = indexFile.getFileNumber(); + IncludeEntry[] tempEntries = addsTree.getIncludeEntries(); + for (int i=0; i failed to generate tree " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$ + e.printStackTrace(); + } + this.manager.removeTree(this.dependencyTreePath); + return false; + } finally { + monitor.exitRead(); // free read lock + } + return true; + } + + public int hashCode() { + return this.project.hashCode(); + } + + protected Integer updatedIndexState() { + return DependencyManager.REBUILDING_STATE; + } + + public String toString() { + return "calculating dependency tree for project " + this.project.getFullPath(); //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IDependencyTree.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IDependencyTree.java new file mode 100644 index 00000000000..5f3198cb997 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IDependencyTree.java @@ -0,0 +1,82 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.internal.core.index.IDocument; +import org.eclipse.cdt.internal.core.index.IQueryResult; +import org.eclipse.core.runtime.IPath; + +public interface IDependencyTree { + /** + * Adds the given document to the index. + */ + void add(IDocument document, String docPath, IScannerInfo newInfo) throws IOException; + /** + * Empties the index. + */ + void empty() throws IOException; + /** + * Returns the index file on the disk. + */ + File getIndexFile(); + /** + * Returns the number of documents indexed. + */ + int getNumDocuments() throws IOException; + /** + * Returns the number of unique words indexed. + */ + int getNumIncludes() throws IOException; + /** + * Returns the path corresponding to a given document number + */ + String getPath(int documentNumber) throws IOException; + /** + * Ansers true if has some changes to save. + */ + boolean hasChanged(); + /** + * Returns the paths of the documents containing the given word. + */ + IQueryResult[] query(String word) throws IOException; + /** + * Returns the paths of the documents whose names contain the given word. + */ + IQueryResult[] queryInDocumentNames(String word) throws IOException; + + /** + * Removes the corresponding document from the tree. + */ + void remove(String documentName) throws IOException; + /** + * Saves the index on the disk. + */ + void save() throws IOException; + /** + * Gets the files that are included by the passed in file. + */ + String[] getFileDependencies(IPath filePath) throws IOException; + // TODO: BOG Debug Method Take out + /** + * Prints all of the IncludeEntries for this project. + */ + public void printIncludeEntries(); + // TODO: BOG Debug Method Take out + /** + * Prints all of the IndexedFiles for this project. + */ + public void printIndexedFiles(); +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IPreprocessorOutput.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IPreprocessorOutput.java new file mode 100644 index 00000000000..109545eb7f0 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/IPreprocessorOutput.java @@ -0,0 +1,20 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; + +import org.eclipse.cdt.internal.core.index.IDocument; + +public interface IPreprocessorOutput { + public void addDocument(IDocument document); + public void addRef(char[] word); + public void addRef(String word); +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/ISourceDependency.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/ISourceDependency.java new file mode 100644 index 00000000000..eb6e35293ab --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/ISourceDependency.java @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; + +public interface ISourceDependency { + IProject[] getProjects(IFile file); + String[] getFileDependencies(IProject project, IFile file); +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/PreprocessorOutput.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/PreprocessorOutput.java new file mode 100644 index 00000000000..97dfb5bb04c --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/PreprocessorOutput.java @@ -0,0 +1,58 @@ +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency; +import org.eclipse.cdt.core.parser.ast.IASTInclusion; +import org.eclipse.cdt.internal.core.index.IDocument; +import org.eclipse.cdt.internal.core.index.impl.IndexedFile; +import org.eclipse.cdt.internal.core.sourcedependency.impl.InMemoryTree; + + +public class PreprocessorOutput implements IPreprocessorOutput { + protected InMemoryTree tree; + protected IndexedFile indexedFile; + protected IDocument document; + + public PreprocessorOutput(InMemoryTree tree) { + this.tree = tree; + } + + public void addInclude(IASTInclusion inclusion, IASTInclusion parent){ + addRef(inclusion.getFullFileName()); + addRelatives(inclusion.getFullFileName(),(parent != null ) ? parent.getFullFileName() : null); + } + + public void addRelatives(String inclusion, String parent) { + if (indexedFile == null) { + throw new IllegalStateException(); + } + tree.addRelatives(indexedFile, inclusion, parent); + } + + public void addDocument(IDocument document) { + if (indexedFile == null) { + indexedFile= tree.addDocument(document); + } else { + throw new IllegalStateException(); + } + } + + public void addRef(char[] word) { + if (indexedFile == null) { + throw new IllegalStateException(); + } + tree.addRef(indexedFile, word); + } + + public void addRef(String word) { + addRef(word.toCharArray()); + } +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/InMemoryTree.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/InMemoryTree.java new file mode 100644 index 00000000000..9fb24a857c3 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/InMemoryTree.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency.impl; + +import org.eclipse.cdt.internal.core.index.IDocument; +import org.eclipse.cdt.internal.core.index.impl.IndexedFile; +import org.eclipse.cdt.internal.core.index.impl.IndexedFileHashedArray; + +public class InMemoryTree { + + /** + * hashtable of IncludeEntrys = includeFiles+numbers of the files they appear in. + */ + protected IncludeEntryHashedArray includes; + /** + * List of IndexedFiles = file name + a unique number. + */ + protected IndexedFileHashedArray files; + /** + * Size of the tree. + */ + protected long footprint; + private int lastId; + + public InMemoryTree() { + init(); + } + /** + * Initialises the fields of the tree + */ + public void init() { + includes= new IncludeEntryHashedArray(501); + files= new IndexedFileHashedArray(101); + footprint= 0; + lastId=0; + } + + public IndexedFile addDocument(IDocument document) { + IndexedFile indexedFile= this.files.add(document); + this.footprint += indexedFile.footprint() + 4; + + return indexedFile; + } + /** + * Adds the references of the include to the tree (reference = number of the file the include belongs to). + */ + protected void addRef(char[] include, int[] references) { + int size= references.length; + int i= 0; + while (i < size) { + if (references[i] != 0) + addRef(include, references[i]); + i++; + } + } + /** + * Looks if the include already exists to the tree and adds the fileNum to this include. + * If the include does not exist, it adds it to the tree. + */ + protected void addRef(char[] include, int fileNum) { + IncludeEntry entry= (IncludeEntry) this.includes.get(include); + if (entry == null) { + entry= new IncludeEntry(include, ++lastId); + entry.addRef(fileNum); + this.includes.add(entry); + } else { + this.footprint += entry.addRef(fileNum); + } + } + + public void addRef(IndexedFile indexedFile, char[] include) { + addRef(include, indexedFile.getFileNumber()); + } + + public void addRef(IndexedFile indexedFile, String include) { + addRef(include.toCharArray(), indexedFile.getFileNumber()); + } + /** + * Returns the indexed file with the given path, or null if such file does not exist. + */ + public IndexedFile getIndexedFile(String path) { + return files.get(path); + } + /** + * @see IIndex#getNumDocuments() + */ + public int getNumFiles() { + return files.size(); + } + /** + * @see IIndex#getNumWords() + */ + public int getNumIncludes() { + return includes.elementSize; + } + + /** + * Returns the include entry corresponding to the given include. + */ + protected IncludeEntry getIncludeEntry(char[] include) { + return (IncludeEntry) includes.get(include); + } + + public void addRelatives(IndexedFile indexedFile, String inclusion, String parent) { + addRelatives(indexedFile.getFileNumber(),inclusion.toCharArray(),(parent != null ) ? parent.toCharArray() : null); + } + + protected void addRelatives(int fileNumber, char[] inclusion, char[] parent) { + IncludeEntry childEntry=null; + IncludeEntry parentEntry=null; + + if (inclusion != null) + childEntry= (IncludeEntry) this.includes.get(inclusion); + + if (parent != null) + parentEntry= (IncludeEntry) this.includes.get(parent); + + + childEntry.addParent(fileNumber,(parentEntry!=null) ? parentEntry.getID() : -1); + + if (parent!=null) + parentEntry.addChild(fileNumber,(childEntry!=null) ? childEntry.getID() : -1); + } + /** + * Returns the include entries contained in the hashtable of includes. + */ + public IncludeEntry[] getIncludeEntries() { + return this.includes.asArray(); + } + + public IndexedFile[] getIndexedFiles(){ + return this.files.asArray(); + } +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java new file mode 100644 index 00000000000..9fdf6ed08a3 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntry.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency.impl; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.cdt.internal.core.search.CharOperation; + +/** + * @author bgheorgh + */ +public class IncludeEntry { + + protected char[] fFile; + protected int fId; + protected int fNumRefs; + protected int[] fRefs; + //TODO: BOG Consider making these arrays... + protected ArrayList fParent; + protected ArrayList fChild; + protected int fNumParent; + protected int fNumChild; + + public IncludeEntry(int id) { + this(CharOperation.NO_CHAR,id); + } + + public IncludeEntry(char[] file, int id) { + fFile = file; + fNumRefs= 0; + fRefs= new int[1]; + fId=id; + + fParent = new ArrayList(5); + fChild = new ArrayList(5); + fNumParent = 0; + fNumChild = 0; + } + /** + * Adds a reference and records the change in footprint. + */ + public int addRef(int fileNum) { + if (fNumRefs > 0 && fRefs[fNumRefs - 1] == fileNum) { + return 0; + } + if (fNumRefs < fRefs.length) { + fRefs[fNumRefs++]= fileNum; + return 0; + } + + int newSize= fNumRefs < 4 ? 4 : fNumRefs * 2; // so will start @ 1, grow to 4, 8, 16, 32, 64 etc. + System.arraycopy(fRefs, 0, fRefs= new int[newSize], 0, fNumRefs); + fRefs[fNumRefs++]= fileNum; + return (newSize - fNumRefs + 1) * 4; + } + + public void addParent(int fileRef, int parentId){ + Node newParent = new Node(fileRef,parentId); + fParent.add(newParent); + fNumParent++; + } + + public void addChild(int fileRef, int parentId){ + Node newChild = new Node(fileRef,parentId); + fChild.add(newChild); + fNumChild++; + } + /** + * Returns the number of references, e.g. the number of files this word appears in. + */ + public int getNumRefs() { + return fNumRefs; + } + /** + * returns the file number in the i position in the list of references. + */ + public int getRef(int i) { + if (i < fNumRefs) return fRefs[i]; + throw new IndexOutOfBoundsException(); + } + /** + * Returns the references of the includeEntry (the number of the files it appears in). + */ + public int[] getRefs() { + int[] result= new int[fNumRefs]; + System.arraycopy(fRefs, 0, result, 0, fNumRefs); + return result; + } + /** + * returns the word of the includeEntry. + */ + public char[] getFile() { + return fFile; + } + + /** + * Clears the includeEntry. + */ + public void reset(char[] word) { + for (int i= fNumRefs; i-- > 0;) { + fRefs[i]= 0; + } + fNumRefs= 0; + fFile= word; + } + + public int getID(){ + return fId; + } + + public String toString() { + StringBuffer tempBuffer = new StringBuffer(); + tempBuffer.append(" 0) tempBuffer.append(','); + tempBuffer.append(' '); + tempBuffer.append(fRefs[i]); + } + tempBuffer.append("}, Parents:{"); + Iterator x = fParent.iterator(); + while (x.hasNext()) + { + Node tempNode = (Node) x.next(); + tempBuffer.append(tempNode.toString()); + if (x.hasNext()) { + tempBuffer.append(','); + tempBuffer.append(' '); + } + } + tempBuffer.append("}, Children:{"); + Iterator y = fChild.iterator(); + while (y.hasNext()) + { + Node tempNode = (Node) y.next(); + tempBuffer.append(tempNode.toString()); + if (y.hasNext()) { + tempBuffer.append(','); + tempBuffer.append(' '); + } + } + tempBuffer.append("} >"); + return tempBuffer.toString(); + } + +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java new file mode 100644 index 00000000000..a7524f531b7 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/IncludeEntryHashedArray.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency.impl; + +import org.eclipse.cdt.internal.core.search.CharOperation; + +public final class IncludeEntryHashedArray { + + public IncludeEntry elements[]; + public int elementSize; // number of elements in the table + public int threshold; + + public IncludeEntryHashedArray(int size) { + if (size < 7) size = 7; + this.elements = new IncludeEntry[2 * size + 1]; + this.elementSize = 0; + this.threshold = size + 1; // size is the expected number of elements + } + + public IncludeEntry add(IncludeEntry entry) { + int length = elements.length; + char[] word = entry.getFile(); + int index = CharOperation.hashCode(word) % length; + IncludeEntry current; + while ((current = elements[index]) != null) { + if (CharOperation.equals(current.getFile(), word)) return elements[index] = entry; + if (++index == length) index = 0; + } + elements[index] = entry; + + // assumes the threshold is never equal to the size of the table + if (++elementSize > threshold) grow(); + return entry; + } + + public IncludeEntry[] asArray() { + IncludeEntry[] array = new IncludeEntry[elementSize]; + for (int i = 0, j = 0, length = elements.length; i < length; i++) { + IncludeEntry current = elements[i]; + if (current != null) array[j++] = current; + } + return array; + } + + public IncludeEntry get(char[] word) { + int length = elements.length; + int index = CharOperation.hashCode(word) % length; + IncludeEntry current; + while ((current = elements[index]) != null) { + if (CharOperation.equals(current.getFile(), word)) return current; + if (++index == length) index = 0; + } + return null; + } + + private void grow() { + IncludeEntryHashedArray newArray = new IncludeEntryHashedArray(elementSize * 2); // double the number of expected elements + for (int i = 0, length = elements.length; i < length; i++) + if (elements[i] != null) + newArray.add(elements[i]); + + this.elements = newArray.elements; + this.elementSize = newArray.elementSize; + this.threshold = newArray.threshold; + } + + public String toString() { + String s = ""; //$NON-NLS-1$ + IncludeEntry[] entries = asArray(); + for (int i = 0, length = entries.length; i < length; i++) + s += entries[i].toString() + "\n"; //$NON-NLS-1$ + return s; + } + +} diff --git a/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/Node.java b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/Node.java new file mode 100644 index 00000000000..2d608b7d271 --- /dev/null +++ b/core/org.eclipse.cdt.core/dependency/org/eclipse/cdt/internal/core/sourcedependency/impl/Node.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.sourcedependency.impl; + +/** + * @author bgheorgh + */ +public class Node { + + int fileRef; + int nodeId; + + public Node(int file, int id){ + this.fileRef = file; + this.nodeId = id; + } + + public int getFileRef(){ + return fileRef; + } + + public int getNodeId(){ + return nodeId; + } + + public String toString() { + StringBuffer tempBuffer = new StringBuffer(); + tempBuffer.append("[FileRef: "); + tempBuffer.append(fileRef); + tempBuffer.append(", Id: "); + tempBuffer.append(nodeId); + tempBuffer.append("]"); + return tempBuffer.toString(); + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java index eeb2d46844f..b221eca742b 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java @@ -9,6 +9,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.internal.core.model.BatchOperation; import org.eclipse.cdt.internal.core.model.CModelManager; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -226,4 +227,11 @@ public class CoreModel { return manager.getIndexManager(); } + public void startDependencyService() { + manager.getSourceDependencyManager().reset(); + } + + public DependencyManager getDependencyManager(){ + return manager.getSourceDependencyManager(); + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index a0a6c7def6e..285b3054c4d 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -43,6 +43,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager; public class CModelManager implements IResourceChangeListener { @@ -777,4 +778,8 @@ public class CModelManager implements IResourceChangeListener { this.getIndexManager().discardJobs(project.getName()); } + + public DependencyManager getSourceDependencyManager() { + return this.fDeltaProcessor.sourceDependencyManager; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java index 66e7db44132..dcfe254fdd4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/DeltaProcessor.java @@ -21,6 +21,7 @@ import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.IPath; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager; /** * This class is used by CModelManager to convert @@ -36,7 +37,9 @@ public class DeltaProcessor { protected CElementDelta fCurrentDelta; protected IndexManager indexManager = new IndexManager(); - + + protected DependencyManager sourceDependencyManager = new DependencyManager(); + /* The C element that was last created (see createElement(IResource). * This is used as a stack of C elements (using getParent() to pop it, and * using the various get*(...) to push it. */ diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index ca75f958b2f..109e6adb7a2 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -189,6 +189,9 @@ public class CCorePlugin extends Plugin { //Fired up the new indexer fCoreModel.startIndexing(); + //Fire up dependency manager + fCoreModel.startDependencyService(); + fDescriptorManager = new CDescriptorManager(); fDescriptorManager.startup(); diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 0c1db86dc02..9e28a1ded7b 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,7 @@ +2003-07-23 Bogdan Gheorghe + Added checkbox to Indexer tab to turn on dependency tree + service + 2003-07-21 Bogdan Gheorghe Update to CSearchResultLabelProvider to ensure that search labels show up on subsequent runs. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IndexerBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IndexerBlock.java index 3cfbc96147e..dd5c0e2925b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IndexerBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IndexerBlock.java @@ -8,6 +8,7 @@ package org.eclipse.cdt.ui.wizards; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.index.IndexModel; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager; import org.eclipse.cdt.utils.ui.swt.IValidation; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; @@ -20,6 +21,7 @@ import org.eclipse.swt.widgets.Composite; public class IndexerBlock implements IWizardTab { private Button indexerSwitch; private Button indexerSwitch2; + private Button dTreeSwitch; IProject project; IValidation page; @@ -48,6 +50,12 @@ public class IndexerBlock implements IWizardTab { indexerSwitch2.setAlignment(SWT.LEFT); indexerSwitch2.setText("Enable NEW indexing service for this project"); indexerSwitch2.setSelection(false); + + dTreeSwitch = new Button(composite, SWT.CHECK | SWT.RIGHT); + dTreeSwitch.setAlignment(SWT.LEFT); + dTreeSwitch.setText("Enable dependency tree service for this project"); + dTreeSwitch.setSelection(false); + return composite; } @@ -60,6 +68,9 @@ public class IndexerBlock implements IWizardTab { IndexManager newIndexer = CCorePlugin.getDefault().getCoreModel().getIndexManager(); newIndexer.setEnabled(project, indexerSwitch2.getSelection()); + + DependencyManager depManager = CCorePlugin.getDefault().getCoreModel().getDependencyManager(); + depManager.setEnabled(project, dTreeSwitch.getSelection()); } @@ -98,11 +109,15 @@ public class IndexerBlock implements IWizardTab { } if (indexerSwitch2 != null) { - //indexerSwitch.setAlignment(SWT.LEFT); - //indexerSwitch.setText("Enable indexing service for this project"); indexerSwitch2.setSelection(newIndexer.isEnabled(project)); } + DependencyManager depManager = CCorePlugin.getDefault().getCoreModel().getDependencyManager(); + + if (dTreeSwitch != null) { + dTreeSwitch.setSelection(depManager.isEnabled(project)); + } + }