From 4e149fbde7841935336ee794a5df78d0f3422dc0 Mon Sep 17 00:00:00 2001
From: Markus Schorn <markus.schorn@windriver.com>
Date: Mon, 2 Mar 2009 15:50:43 +0000
Subject: [PATCH] API to check whether a declaration is from a file actually
 included by a translation unit, bug 254844.

---
 .../internal/index/tests/IndexBugsTests.java  | 40 +++++++++++++++++++
 .../cdt/core/dom/ast/IASTTranslationUnit.java | 28 ++++++++-----
 .../eclipse/cdt/core/index/IIndexFileSet.java | 11 ++++-
 .../core/index/IIndexFragmentFileSet.java     |  5 +++
 .../cdt/internal/core/index/IndexFileSet.java | 12 ++++++
 .../cdt/internal/core/pdom/PDOMFileSet.java   |  7 ++++
 6 files changed, 92 insertions(+), 11 deletions(-)

diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
index daea1485b70..864f2c532d4 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
@@ -50,6 +50,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
 import org.eclipse.cdt.core.index.IIndex;
 import org.eclipse.cdt.core.index.IIndexBinding;
 import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.index.IIndexFileSet;
 import org.eclipse.cdt.core.index.IIndexInclude;
 import org.eclipse.cdt.core.index.IIndexMacro;
 import org.eclipse.cdt.core.index.IIndexManager;
@@ -1675,4 +1676,43 @@ public class IndexBugsTests extends BaseTestCase {
 			fIndex.releaseReadLock();
 		}
 	}
+	
+	// int a;
+	
+	// #include "a.h"
+	// void test() {a=0;}
+	public void testDeclarationForBinding_Bug254844() throws Exception {
+		String[] contents= getContentsForTest(2);
+		final IIndexManager indexManager = CCorePlugin.getIndexManager();
+		IFile a= TestSourceReader.createFile(fCProject.getProject(), "a.h", contents[0]);
+		IFile b= TestSourceReader.createFile(fCProject.getProject(), "b.h", contents[0]);
+		IFile source= TestSourceReader.createFile(fCProject.getProject(), "source.cpp", contents[1]);
+		indexManager.reindex(fCProject);
+		waitForIndexer();
+		ITranslationUnit tu= (ITranslationUnit) CoreModel.getDefault().create(source);
+		fIndex.acquireReadLock();
+		try {
+			IASTTranslationUnit ast= tu.getAST(fIndex, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
+			IIndexFileSet fileset= ast.getIndexFileSet();
+			IBinding var= getBindingFromASTName(ast, contents[1], "a=", 1, IBinding.class);
+			IName[] decls= ast.getDeclarations(var);
+			assertEquals(2, decls.length);
+			int check= 0;
+			for (int i = 0; i < decls.length; i++) {
+				IName name = decls[i];
+				assert name instanceof IIndexName;
+				IIndexName iName= (IIndexName) name;
+				if (iName.getFileLocation().getFileName().endsWith("a.h")) {
+					check |= 1;
+					assertTrue(fileset.contains(iName.getFile()));
+				} else {
+					check |= 2;
+					assertFalse(fileset.contains(iName.getFile()));
+				}
+			}
+			assertEquals(3, check);
+		} finally {
+			fIndex.releaseReadLock();
+		}
+	}
 }
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
index 52b3621f251..bd76544f166 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
@@ -14,6 +14,7 @@ package org.eclipse.cdt.core.dom.ast;
 import org.eclipse.cdt.core.dom.ILinkage;
 import org.eclipse.cdt.core.dom.IName;
 import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexFileSet;
 import org.eclipse.cdt.core.parser.ParserLanguage;
 import org.eclipse.core.runtime.IAdaptable;
 
@@ -244,11 +245,13 @@ public interface IASTTranslationUnit extends IASTNode, IASTDeclarationListOwner,
     public IIndex getIndex();
     
     /**
-     * Set the Index to be used for this translation unit.
-     * 
-     * @param index
+     * Return the set of files that have been skipped because they have been part of the index
+     * prior to creating this AST, or <code>null</code> if not available.
+     * Applies only, if AST was created with an index and the option to skip headers found in the
+     * index.
+     * @since 5.1
      */
-    public void setIndex(IIndex index);
+    IIndexFileSet getIndexFileSet();
     
 	/**
 	 * In case the ast was created in a way that supports comment parsing,
@@ -271,11 +274,6 @@ public interface IASTTranslationUnit extends IASTNode, IASTDeclarationListOwner,
 	 */
 	public boolean isHeaderUnit();
 
-	/**
-	 * Sets whether this ast represents a header file.
-	 */
-	public void setIsHeaderUnit(boolean headerUnit);
-	
 	/**
 	 * Returns the node factory that was used to build the AST.
 	 * 
@@ -283,6 +281,18 @@ public interface IASTTranslationUnit extends IASTNode, IASTDeclarationListOwner,
 	 * @since 5.1
 	 */
 	public INodeFactory getASTNodeFactory();
+
+    /**
+     * Set the Index to be used for this translation unit.
+     * @noreference This method is not intended to be referenced by clients.
+     */
+    public void setIndex(IIndex index);
+
+	/**
+	 * Sets whether this ast represents a header file.
+	 * @noreference This method is not intended to be referenced by clients.
+	 */
+	public void setIsHeaderUnit(boolean headerUnit);
 	
 	/**
 	 * Causes this node and all the nodes rooted at this node to become immutable. 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
index 0ded38106af..aa82e44da17 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
@@ -12,6 +12,7 @@ package org.eclipse.cdt.core.index;
 
 import org.eclipse.cdt.core.dom.ast.IBinding;
 import org.eclipse.cdt.internal.core.index.IndexFileSet;
+import org.eclipse.core.runtime.CoreException;
 
 /**
  * File set for index files. Can be used to filter file-local bindings.
@@ -22,15 +23,21 @@ import org.eclipse.cdt.internal.core.index.IndexFileSet;
 public interface IIndexFileSet {
 	IIndexFileSet EMPTY = new IndexFileSet();
 
+	/**
+	 * Returns whether the given file is part of this file set.
+	 * @since 5.1
+	 */
+	boolean contains(IIndexFile file) throws CoreException;
+
 	/**
 	 * Returns an array of bindings where all local bindings that are not part of this file-set
 	 * have been removed.
 	 */
-	IBinding[] filterFileLocalBindings(IBinding[] bindings);
+	IBinding[] filterFileLocalBindings(IBinding[] bindings);	
 
 	/**
 	 * Adds a file to this set.
-	 * @param indexFile
+	 * @noreference This method is not intended to be referenced by clients.
 	 */
 	void add(IIndexFile indexFile);
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
index 95da81bee1d..30d0b3347ff 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
@@ -24,4 +24,9 @@ public interface IIndexFragmentFileSet {
 	 * Adds the fragment file to the file-set.
 	 */
 	void add(IIndexFragmentFile fragFile);
+
+	/**
+	 * Returns whether the file set contains the given file.
+	 */
+	boolean contains(IIndexFragmentFile file) throws CoreException;
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
index 9240373c0e4..78220069169 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
@@ -79,4 +79,16 @@ public class IndexFileSet implements IIndexFileSet {
 		}
 		return result;
 	}
+
+	public boolean contains(IIndexFile file) throws CoreException {
+		if (!(file instanceof IIndexFragmentFile))
+			return false;
+		
+		IIndexFragmentFile ifile= (IIndexFragmentFile) file;
+		IIndexFragmentFileSet subSet= fSubSets.get(ifile.getIndexFragment());
+		if (subSet != null) {
+			return subSet.contains(ifile);
+		}
+		return false;
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
index defa010f95f..66e1a214146 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
@@ -32,4 +32,11 @@ public class PDOMFileSet implements IIndexFragmentFileSet {
 		PDOMBinding pdomBinding= (PDOMBinding) fb;
 		return fFileIDs.contains(pdomBinding.getLocalToFileRec());
 	}
+
+	public boolean contains(IIndexFragmentFile file) throws CoreException {
+		if (file instanceof PDOMFile) {
+			return fFileIDs.contains(((PDOMFile) file).getRecord());
+		}
+		return false;
+	}
 }