diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java new file mode 100644 index 00000000000..737ead8c376 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.index.tests; + +import java.io.IOException; +import java.util.regex.Pattern; + +import junit.framework.TestSuite; + +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.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexName; +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.cdt.internal.core.CCoreInternals; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; + +public class EnclosingNamesTest extends BaseTestCase { + private static final IProgressMonitor NPM = new NullProgressMonitor(); + private ICProject fCProject; + protected IIndex fIndex; + + public EnclosingNamesTest(String name) { + super(name); + } + + public static TestSuite suite() { + return suite(EnclosingNamesTest.class); + } + + protected void setUp() throws CoreException { + fCProject= CProjectHelper.createCCProject("__encNamesTest__", "bin", IPDOMManager.ID_FAST_INDEXER); + CCoreInternals.getPDOMManager().reindex(fCProject); + fIndex= CCorePlugin.getIndexManager().getIndex(fCProject); + } + + protected void tearDown() throws CoreException { + if (fCProject != null) { + CProjectHelper.delete(fCProject); + } + } + + protected IProject getProject() { + return fCProject.getProject(); + } + + protected StringBuffer[] getContentsForTest(int blocks) throws IOException { + return TestSourceReader.getContentsForTest( + CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), blocks); + } + + protected IFile createFile(IContainer container, String fileName, String contents) throws Exception { + return TestSourceReader.createFile(container, new Path(fileName), contents); + } + + protected void waitForIndexer() { + assertTrue(CCorePlugin.getIndexManager().joinIndexer(10000, NPM)); + } + + protected Pattern[] getPattern(String qname) { + String[] parts= qname.split("::"); + Pattern[] result= new Pattern[parts.length]; + for (int i = 0; i < result.length; i++) { + result[i]= Pattern.compile(parts[i]); + } + return result; + } + + protected void waitUntilFileIsIndexed(IFile file, int time) throws Exception { + TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time); + } + + // void func(); + // int var; + // + // void main() { + // func(); + // var=1; + // }; + public void testNestingWithFunction() throws Exception { + waitForIndexer(); + String content= getContentsForTest(1)[0].toString(); + IFile file= createFile(getProject().getProject(), "test.cpp", content); + waitUntilFileIsIndexed(file, 4000); + + fIndex.acquireReadLock(); + try { + IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, NPM); + assertLength(1, mainBS); + IIndexBinding mainB= mainBS[0]; + + IIndexName[] names= fIndex.findDefinitions(mainB); + assertLength(1, names); + IIndexName main= names[0]; + + assertNull(main.getEnclosingDefinition()); + IIndexName[] enclosed= main.getEnclosedNames(); + assertLength(2, enclosed); + assertName("func", enclosed[0]); + assertName("var", enclosed[1]); + + IIndexName enclosing= enclosed[0].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("main", enclosing); + + enclosing= enclosed[1].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("main", enclosing); + } + finally { + fIndex.releaseReadLock(); + } + } + + private void assertName(String name, IIndexName iname) { + assertEquals(name, new String(iname.toCharArray())); + } + + private void assertLength(int length, Object[] array) { + assertNotNull(array); + assertEquals(length, array.length); + } + + // class C { + // public: + // void func(); + // int var; + // }; + // + // void main() { + // C c; + // c.func(); + // c.var=1; + // }; + // void C::func() { + // func(); + // var=1; + // }; + + + public void testNestingWithMethod() throws Exception { + waitForIndexer(); + String content= getContentsForTest(1)[0].toString(); + IFile file= createFile(getProject().getProject(), "test.cpp", content); + waitUntilFileIsIndexed(file, 4000); + + fIndex.acquireReadLock(); + try { + IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, NPM); + assertLength(1, mainBS); + IIndexBinding mainB= mainBS[0]; + + IIndexName[] names= fIndex.findDefinitions(mainB); + assertLength(1, names); + IIndexName main= names[0]; + + assertNull(main.getEnclosingDefinition()); + IIndexName[] enclosed= main.getEnclosedNames(); + assertLength(3, enclosed); + assertName("C", enclosed[0]); + assertName("func", enclosed[1]); + assertName("var", enclosed[2]); + + IIndexName enclosing= enclosed[0].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("main", enclosing); + + enclosing= enclosed[1].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("main", enclosing); + + enclosing= enclosed[2].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("main", enclosing); + + IIndexBinding funcB= fIndex.findBinding(enclosed[1]); + assertNotNull(funcB); + names= fIndex.findDefinitions(funcB); + assertLength(1, names); + IIndexName funcdef= names[0]; + + assertNull(funcdef.getEnclosingDefinition()); + enclosed= funcdef.getEnclosedNames(); + assertLength(3, enclosed); + assertName("C", enclosed[0]); + assertName("func", enclosed[1]); + assertName("var", enclosed[2]); + + enclosing= enclosed[0].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("func", enclosing); + + enclosing= enclosed[1].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("func", enclosing); + + enclosing= enclosed[2].getEnclosingDefinition(); + assertNotNull(enclosing); + assertName("func", enclosing); + } + finally { + fIndex.releaseReadLock(); + } + } + +} 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 f3e90ee0dec..37a5d28d69c 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 @@ -74,8 +74,9 @@ public class IndexBugsTests extends BaseTestCase { return fCProject.getProject(); } - protected String readTaggedComment(final String tag) throws IOException { - return TestSourceReader.readTaggedComment(CTestPlugin.getDefault().getBundle(), "parser", getClass(), tag); + protected StringBuffer[] getContentsForTest(int blocks) throws IOException { + return TestSourceReader.getContentsForTest( + CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), blocks); } protected IFile createFile(IContainer container, String fileName, String contents) throws Exception { @@ -99,7 +100,6 @@ public class IndexBugsTests extends BaseTestCase { TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time); } - // {bug162011} // namespace ns162011 { // class Class162011 { // friend void function162011(Class162011); @@ -107,7 +107,7 @@ public class IndexBugsTests extends BaseTestCase { // void function162011(Class162011 x){}; // } public void testBug162011() throws Exception { - String content = readTaggedComment("bug162011"); + String content = getContentsForTest(1)[0].toString(); String fileName = "bug162011.cpp"; String funcName = "function162011"; String nsName = "ns162011"; @@ -247,13 +247,12 @@ public class IndexBugsTests extends BaseTestCase { } } - // {test164500} // #define macro164500 1 // #undef macro164500 // #define macro164500 2 public void test164500() throws Exception { waitForIndexer(); - String content= readTaggedComment("test164500"); + String content= getContentsForTest(1)[0].toString(); IFile file= TestSourceReader.createFile(fCProject.getProject(), "test164500.cpp", content); TestSourceReader.waitUntilFileIsIndexed(fIndex, file, 4000); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java index 813fef12e04..719daa4c9ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java @@ -7,6 +7,7 @@ * * Contributors: * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -108,4 +109,12 @@ public interface IASTNode { */ public String getRawSignature(); + /** + * Returns whether this node contains the given one. The decision is made + * purly on location information and therefore the method is fast. + * @param node the node to check + * @return whether this node contains the given one. + * @since 4.0 + */ + public boolean contains(IASTNode node); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java index 36b24b179a0..7c6b79fa1fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java @@ -51,4 +51,20 @@ public interface IIndexName extends IName { * Returns the length of the name. */ public int getNodeLength(); + + /** + * Returns the name of the definition that contains this name. + * May return null. + * Currently this is implemented for function and method definitions, only. + */ + public IIndexName getEnclosingDefinition() throws CoreException; + + /** + * Returns the names of the references contained in this definition. + * Returns null, if the name is not a definition. + * + * Currently the method works with function definitions, only. + */ + public IIndexName[] getEnclosedNames() throws CoreException; + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java index 9f2d687e3af..209e9cba88a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; @@ -112,4 +113,12 @@ public abstract class ASTNode implements IASTNode { return true; } + public boolean contains(IASTNode node) { + if (node instanceof ASTNode) { + ASTNode astNode= (ASTNode) node; + return offset <= astNode.offset && + astNode.offset+astNode.length <= offset+length; + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java index e6f1c54b6e3..0b1ba63822a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java @@ -35,7 +35,7 @@ public interface IWritableIndex extends IIndex { */ void setFileContent(IIndexFragmentFile sourceFile, IASTPreprocessorIncludeStatement[] includes, - IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException; + IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException; /** * Clears the entire index. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java index f17787f1d1b..091cfaa3a2e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java @@ -41,7 +41,7 @@ public interface IWritableIndexFragment extends IIndexFragment { */ void addFileContent(IIndexFragmentFile sourceFile, IASTPreprocessorIncludeStatement[] includes, IIndexFragmentFile[] destFiles, - IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException; + IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException; /** * Acquires a write lock, while giving up a certain amount of read locks. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java index 27a290d472c..dd43f620d71 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java @@ -57,7 +57,7 @@ public class WritableCIndex extends CIndex implements IWritableIndex { public void setFileContent(IIndexFragmentFile file, IASTPreprocessorIncludeStatement[] includes, - IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException { + IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException { IIndexFragment indexFragment = file.getIndexFragment(); assert isWritableFragment(indexFragment); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 50fbf929165..0eff27a8552 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -64,7 +64,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { private Database db; - public static final int VERSION = 16; + public static final int VERSION = 17; // 0 - the beginning of it all // 1 - first change to kick off upgrades // 2 - added file inclusions @@ -82,6 +82,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { // 14 - added timestamps for files (bug 149571) // 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540). // 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing + // 17 - use single linked list for names in file, adds a link to enclosing defintion name. public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; @@ -460,7 +461,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM { } } - public void releaseWriteLock() { + final public void releaseWriteLock() { releaseWriteLock(0); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index 39f849286a1..797c1375bcf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.core.runtime.CoreException; @@ -35,22 +36,14 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { public void addFileContent(IIndexFragmentFile sourceFile, IASTPreprocessorIncludeStatement[] includes, IIndexFragmentFile[] destFiles, - IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException { + IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException { assert sourceFile.getIndexFragment() == this; + assert includes.length == destFiles.length; PDOMFile pdomFile = (PDOMFile) sourceFile; pdomFile.addIncludesTo(destFiles, includes); pdomFile.addMacros(macros); - for (int i = 0; i < names.length; i++) { - IASTName name= names[i]; - PDOMLinkage linkage= createLinkage(name.getLinkage().getID()); - if (linkage == null) { - CCorePlugin.log(MessageFormat.format(Messages.WritablePDOM_error_unknownLinkage, new Object[]{name.getLinkage()})); - } - else { - linkage.addName(name, pdomFile); - } - } + pdomFile.addNames(names); } public void clearFile(IIndexFragmentFile file) throws CoreException { @@ -61,4 +54,16 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { public void clear() throws CoreException { super.clear(); } + + public PDOMBinding addBinding(IASTName name) throws CoreException { + PDOMBinding result= null; + PDOMLinkage linkage= createLinkage(name.getLinkage().getID()); + if (linkage == null) { + CCorePlugin.log(MessageFormat.format(Messages.WritablePDOM_error_unknownLinkage, new Object[]{name.getLinkage()})); + } + else { + result= linkage.addBinding(name); + } + return result; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index 10304ebf51f..918137bfa47 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -12,8 +12,10 @@ package org.eclipse.cdt.internal.core.pdom.dom; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.index.IIndexInclude; @@ -22,6 +24,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.pdom.PDOM; +import org.eclipse.cdt.internal.core.pdom.WritablePDOM; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; @@ -149,15 +152,6 @@ public class PDOMFile implements IIndexFragmentFile { pdom.getDB().putInt(record + FIRST_NAME, namerec); } - public void addName(PDOMName name) throws CoreException { - PDOMName firstName = getFirstName(); - if (firstName != null) { - name.setNextInFile(firstName); - firstName.setPrevInFile(name); - } - setFirstName(name); - } - public PDOMInclude getFirstInclude() throws CoreException { int increc = pdom.getDB().getInt(record + FIRST_INCLUDE); return increc != 0 ? new PDOMInclude(pdom, increc) : null; @@ -205,6 +199,36 @@ public class PDOMFile implements IIndexFragmentFile { } } + public void addNames(IASTName[][] names) throws CoreException { + assert getFirstName() == null; + HashMap nameCache= new HashMap(); + PDOMName lastName= null; + for (int i = 0; i < names.length; i++) { + IASTName[] name = names[i]; + PDOMName caller= (PDOMName) nameCache.get(name[1]); + PDOMName pdomName = createPDOMName(name[0], caller); + if (pdomName != null) { + nameCache.put(name[0], pdomName); + if (lastName == null) { + setFirstName(pdomName); + } + else { + lastName.setNextInFile(pdomName); + } + lastName= pdomName; + } + } + } + + private PDOMName createPDOMName(IASTName name, PDOMName caller) throws CoreException { + PDOMName result= null; + PDOMBinding binding= ((WritablePDOM) pdom).addBinding(name); + if (binding != null) { + result= new PDOMName(pdom, name, this, binding, caller); + } + return result; + } + public void clear() throws CoreException { // Remove the includes PDOMInclude include = getFirstInclude(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index e8ed93c983e..27fd71cd875 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -168,7 +168,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IBindingIdent }; } - public abstract PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException; + public abstract PDOMBinding addBinding(IASTName name) throws CoreException; public abstract PDOMBinding adaptBinding(IBinding binding) throws CoreException; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java index 6b613d21fba..e7427d6393c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java @@ -11,10 +11,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; +import java.util.ArrayList; + import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.index.IIndexFile; +import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.index.IIndexProxyBinding; @@ -32,23 +35,23 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { private final int record; private static final int FILE_REC_OFFSET = 0; - private static final int FILE_PREV_OFFSET = 4; - private static final int FILE_NEXT_OFFSET = 8; + private static final int FILE_NEXT_OFFSET = 4; + private static final int CALLER_REC_OFFSET = 8; private static final int BINDING_REC_OFFSET = 12; private static final int BINDING_PREV_OFFSET = 16; private static final int BINDING_NEXT_OFFSET = 20; private static final int NODE_OFFSET_OFFSET = 24; - private static final int NODE_LENGTH_OFFSET = 28; - private static final int FLAGS = 32; + private static final int NODE_LENGTH_OFFSET = 28; // short + private static final int FLAGS = 30; // byte - private static final int RECORD_SIZE = 33; + private static final int RECORD_SIZE = 31; private static final int IS_DECLARATION = 1; private static final int IS_DEFINITION = 2; private static final int IS_REFERENCE = 3; - public PDOMName(PDOM pdom, IASTName name, PDOMFile file, PDOMBinding binding) throws CoreException { + public PDOMName(PDOM pdom, IASTName name, PDOMFile file, PDOMBinding binding, PDOMName caller) throws CoreException { this.pdom = pdom; Database db = pdom.getDB(); record = db.malloc(RECORD_SIZE); @@ -80,14 +83,15 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { db.putInt(record + BINDING_REC_OFFSET, binding.getRecord()); } - // Hook us up the the liked name list from file db.putInt(record + FILE_REC_OFFSET, file.getRecord()); - file.addName(this); + if (caller != null) { + db.putInt(record + CALLER_REC_OFFSET, caller.getRecord()); + } // Record our location in the file IASTFileLocation fileloc = name.getFileLocation(); db.putInt(record + NODE_OFFSET_OFFSET, fileloc.getNodeOffset()); - db.putInt(record + NODE_LENGTH_OFFSET, fileloc.getNodeLength()); + db.putShort(record + NODE_LENGTH_OFFSET, (short) fileloc.getNodeLength()); } public PDOMName(PDOM pdom, int nameRecord) { @@ -147,6 +151,15 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { int filerec = pdom.getDB().getInt(record + FILE_REC_OFFSET); return filerec != 0 ? new PDOMFile(pdom, filerec) : null; } + + public IIndexName getEnclosingDefinition() throws CoreException { + int namerec = getEnclosingDefinitionRecord(); + return namerec != 0 ? new PDOMName(pdom, namerec) : null; + } + + private int getEnclosingDefinitionRecord() throws CoreException { + return pdom.getDB().getInt(record + CALLER_REC_OFFSET); + } public PDOMName getNextInFile() throws CoreException { return getNameField(FILE_NEXT_OFFSET); @@ -155,15 +168,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public void setNextInFile(PDOMName name) throws CoreException { setNameField(FILE_NEXT_OFFSET, name); } - - public PDOMName getPrevInFile() throws CoreException { - return getNameField(FILE_PREV_OFFSET); - } - - public void setPrevInFile(PDOMName name) throws CoreException { - setNameField(FILE_PREV_OFFSET, name); - } - + public PDOMBinding resolveBinding() { try { int bindingRecord = pdom.getDB().getInt(record + BINDING_REC_OFFSET); @@ -248,7 +253,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public int getNodeLength() { try { - return pdom.getDB().getInt(record + NODE_LENGTH_OFFSET); + return pdom.getDB().getShort(record + NODE_LENGTH_OFFSET); } catch (CoreException e) { CCorePlugin.log(e); return 0; @@ -298,4 +303,16 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public IIndexProxyBinding getBinding() throws CoreException { return getPDOMBinding(); } + + public IIndexName[] getEnclosedNames() throws CoreException { + ArrayList result= new ArrayList(); + PDOMName name= getNextInFile(); + while (name != null) { + if (name.getEnclosingDefinitionRecord() == record) { + result.add(name); + } + name= name.getNextInFile(); + } + return (IIndexName[]) result.toArray(new IIndexName[result.size()]); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java index ab671442e13..7f0cee55d42 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java @@ -43,9 +43,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.FindBindingByLinkageConstant; import org.eclipse.cdt.internal.core.pdom.dom.FindEquivalentBinding; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Status; @@ -85,9 +83,7 @@ class PDOMCLinkage extends PDOMLinkage { return new GCCLanguage(); } - - - public PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException { + public PDOMBinding addBinding(IASTName name) throws CoreException { if (name == null) return null; @@ -149,10 +145,6 @@ class PDOMCLinkage extends PDOMLinkage { } catch (DOMException e) { throw new CoreException(Util.createStatus(e)); } - - if (pdomBinding != null) - new PDOMName(pdom, name, file, pdomBinding); - return pdomBinding; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java index 78af27ff078..087ebee6362 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java @@ -316,7 +316,9 @@ ICPPClassScope, IPDOMMemberOwner { } } - public void addChild(PDOMNode member) throws CoreException {addMember(member);} + public void addChild(PDOMNode member) throws CoreException { + addMember(member); + } public ICPPConstructor[] getConstructors() throws DOMException { // TODO diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index b54ac41eefc..df0c7e16fb0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -15,7 +15,6 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; -import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; @@ -69,9 +68,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.FindBindingByLinkageConstant; import org.eclipse.cdt.internal.core.pdom.dom.FindEquivalentBinding; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError; import org.eclipse.core.runtime.CoreException; @@ -120,8 +117,7 @@ class PDOMCPPLinkage extends PDOMLinkage { return new GPPLanguage(); } - - public PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException { + public PDOMBinding addBinding(IASTName name) throws CoreException { if (name == null || name instanceof ICPPASTQualifiedName) return null; @@ -198,9 +194,6 @@ class PDOMCPPLinkage extends PDOMLinkage { // final processing if (pdomBinding != null) { - // Add in the name - new PDOMName(pdom, name, file, pdomBinding); - // Check if is a base specifier if (pdomBinding instanceof ICPPClassType && name.getParent() instanceof ICPPASTBaseSpecifier) { ICPPASTBaseSpecifier baseNode = (ICPPASTBaseSpecifier)name.getParent(); @@ -297,8 +290,6 @@ class PDOMCPPLinkage extends PDOMLinkage { } private PDOMBinding _resolveBinding(IASTName name) throws CoreException, DOMException { - // mstodo revisit - IBinding origBinding = name.getBinding(); if (origBinding != null) return adaptBinding(origBinding); @@ -398,7 +389,7 @@ class PDOMCPPLinkage extends PDOMLinkage { PDOMBinding pdomFOB = adaptBinding( (ICompositeType) type); FindBindingByLinkageConstant visitor = new FindBindingByLinkageConstant(this, name.toCharArray(), PDOMCPPLinkage.CPPFIELD); try { - ((PDOMBinding)pdomFOB).accept(visitor); + pdomFOB.accept(visitor); } catch (CoreException e) { if (e.getStatus().equals(Status.OK_STATUS)) { return visitor.getResult(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java new file mode 100644 index 00000000000..bfb1ad253c8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.pdom.indexer; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; + +abstract public class IndexerASTVisitor extends ASTVisitor { + private IASTName fDefinitionName; + private IASTNode fDefinition; + + public IndexerASTVisitor() { + shouldVisitNames = true; + shouldVisitDeclarations = true; + } + + abstract public void visit(IASTName name, IASTName definitionName); + + final public int visit(IASTName name) { + if (!(name instanceof ICPPASTQualifiedName)) { + if (fDefinition != null) { + if (!fDefinition.contains(name)) { + fDefinition= null; + fDefinitionName= null; + } + } + if (name != fDefinitionName) { + visit(name, fDefinitionName); + } + } + return PROCESS_CONTINUE; + } + + public int visit(IASTDeclaration decl) { + if (decl instanceof IASTFunctionDefinition) { + IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl; + fDefinition= decl; + fDefinitionName= fdef.getDeclarator().getName(); + if (fDefinitionName instanceof ICPPASTQualifiedName) { + fDefinitionName= ((ICPPASTQualifiedName) fDefinitionName).getLastName(); + } + visit(fDefinitionName, null); + } + return PROCESS_CONTINUE; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java index f00b1630a7d..db7afcf2603 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java @@ -14,15 +14,21 @@ package org.eclipse.cdt.internal.core.pdom.indexer; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMIndexerTask; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexInclude; @@ -240,7 +246,90 @@ public abstract class PDOMIndexerTask implements IPDOMIndexerTask { return fCompletedSources; } - protected IIndexFragmentFile addToIndex(IWritableIndex index, String location, ArrayList[] lists) throws CoreException { + /** + * Extracts a map of names from the ast and returns an array defining the order in + * which the symbols should be added to the index. + * @since 4.0 + */ + protected String[] extractSymbols(IASTTranslationUnit ast, Set legalPaths, final LinkedHashMap symbolMap) { + // includes + final String astFilePath = ast.getFilePath(); + IASTPreprocessorIncludeStatement[] includes = ast.getIncludeDirectives(); + for (int i = includes.length-1; i >= 0; --i) { + IASTPreprocessorIncludeStatement include = includes[i]; + IASTFileLocation sourceLoc = include.getFileLocation(); + String path= sourceLoc != null ? sourceLoc.getFileName() : astFilePath; // command-line includes + if (legalPaths.contains(path)) { + prepareInMap(symbolMap, path); + addToMap(symbolMap, 0, path, include); + } + path= include.getPath(); + if (legalPaths.contains(path)) { + prepareInMap(symbolMap, path); + } + } + if (legalPaths.contains(astFilePath)) { + prepareInMap(symbolMap, ast.getFilePath()); + } + + // macros + IASTPreprocessorMacroDefinition[] macros = ast.getMacroDefinitions(); + for (int i = 0; i < macros.length; ++i) { + IASTPreprocessorMacroDefinition macro = macros[i]; + IASTFileLocation sourceLoc = macro.getFileLocation(); + if (sourceLoc != null) { // skip built-ins and command line macros + String path = sourceLoc.getFileName(); + addToMap(symbolMap, 1, path, macro); + } + } + + // names + ast.accept(new IndexerASTVisitor() { + public void visit(IASTName name, IASTName caller) { + IASTFileLocation nameLoc = name.getFileLocation(); + if (nameLoc != null) { + addToMap(symbolMap, 2, nameLoc.getFileName(), new IASTName[]{name, caller}); + } + } + }); + + Collection temp= symbolMap.keySet(); + int size= temp.size(); + String[] result= new String[temp.size()]; + for (Iterator iter = temp.iterator(); iter.hasNext();) { + result[--size]= (String) iter.next(); + } + return result; + } + + private void addToMap(HashMap map, int idx, String path, Object thing) { + List[] lists= (List[]) map.get(path); + if (lists != null) + lists[idx].add(thing); + } + + private boolean prepareInMap(Map map, String path) { + if (map.get(path) == null) { + Object lists= new ArrayList[]{new ArrayList(), new ArrayList(), new ArrayList()}; + map.put(path, lists); + } + return false; + } + + protected void prepareIndexInsertion(String path, Map symbolMap) { + ArrayList[] arrayLists = ((ArrayList[]) symbolMap.get(path)); + + // reverse the includes + Collections.reverse(arrayLists[0]); + + // resolve the names + ArrayList names= arrayLists[2]; + for (int j=0; j MAX_ERRORS ? PROCESS_ABORT : PROCESS_CONTINUE; - } - } - }); - - for (Iterator iter = symbolMap.entrySet().iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); + for (int i=0; i MAX_ERRORS ? PROCESS_ABORT : PROCESS_CONTINUE; - } - } - }); - - for (Iterator iter = symbolMap.values().iterator(); iter.hasNext();) { + for (int i=0; i