diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 37db7bdd9a3..220421fe029 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -73,7 +73,6 @@ import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IContributedModelBuilder; -import org.eclipse.cdt.core.model.IParent; import org.eclipse.cdt.core.model.IProblemRequestor; import org.eclipse.cdt.core.model.IStructure; import org.eclipse.cdt.core.model.ITranslationUnit; @@ -515,18 +514,6 @@ public class CModelBuilder2 implements IContributedModelBuilder { elements= new CElement[1]; final CElement element= createSimpleDeclaration(parent, declSpecifier, null, isTemplate); elements[0]= element; - } else if (declarators.length == 1 && isCompositeType) { - elements= new CElement[declarators.length]; - final IASTDeclarator declarator= declarators[0]; - CElement element= createTypedefOrFunctionOrVariable(parent, declSpecifier, declarator, isTemplate); - if (element instanceof IParent) { - parent= (Parent)element; - if (!isTemplate) { - setBodyPosition((SourceManipulation)element, declSpecifier.getParent()); - } - } - elements[0]= element; - createSimpleDeclaration(parent, declSpecifier, null, isTemplate); } else { if (isCompositeType) { createSimpleDeclaration(parent, declSpecifier, null, isTemplate); @@ -535,7 +522,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { for (int i= 0; i < declarators.length; i++) { final IASTDeclarator declarator= declarators[i]; final CElement element= createSimpleDeclaration(parent, declSpecifier, declarator, isTemplate); - if (!isTemplate && element instanceof SourceManipulation) { + if (!isTemplate && element instanceof SourceManipulation && declarators.length > 1) { setBodyPosition((SourceManipulation)element, declarator); } elements[i]= element; @@ -800,17 +787,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { } else { final IASTFileLocation classLocation= getMinFileLocation(compositeTypeSpecifier.getNodeLocations()); if (classLocation != null) { - if (compositeTypeSpecifier.getStorageClass() == IASTDeclSpecifier.sc_typedef) { - // fix positions for typedef struct (heuristically) - final int delta= Keywords.TYPEDEF.length() + 1; - element.setIdPos(classLocation.getNodeOffset() + delta, type.length()); - if(!isTemplate){ - final SourceManipulationInfo info= element.getSourceManipulationInfo(); - info.setPos(info.getStartPos() + delta, info.getLength() - delta); - } - } else { - element.setIdPos(classLocation.getNodeOffset(), type.length()); - } + element.setIdPos(classLocation.getNodeOffset(), type.length()); } } // add members @@ -1146,7 +1123,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { // hook up the offsets setIdentifierPosition(info, name); if (!isTemplate) { - setBodyPosition(info, declarator); + setBodyPosition(info, declarator.getParent()); } return element; } diff --git a/core/org.eclipse.cdt.ui.tests/resources/compare/CompareTest.cpp b/core/org.eclipse.cdt.ui.tests/resources/compare/CompareTest.cpp new file mode 100644 index 00000000000..04e7115563d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/compare/CompareTest.cpp @@ -0,0 +1,155 @@ +// include +#include "included.h" + +// macro +#define PRINT(string,msg) printf(string, msg) + +//namespace +namespace MyPackage +{ + // check class + // class + class Hello + { + // protected visibility + protected: + // field + int x; + // method + inline void setX(int X) + { + x = X; + }; + // check nested pachage + // nested namespace + namespace MyNestedPackage { + // check parent nested class + // nested class + class Y + { // public visibility + public: + // constructor + Y(); + // virtual destructor + virtual ~Y(); + }; + // check derived nested class + // derived class + class X : public Y { + // private visibility + private: + // private field + B b; + + public: + // constructor chain + X(int x) : Y(x) { + cout << "In consturctor\n"; + } + // method declaration + int doNothing(); + }; + } + }; + + // check enums + // enum without name + enum { + first = 1, + second, + third + } + ; + // enum with name + enum MyEnum { + f, + s, + t }; + + // check variables + // variable + int v; + // unsigned long variable + unsigned long vuLong; + // unsigned short variable + unsigned short vuShort; + + // check variable declarations + // variable declaration + extern int evar; + // function pointer + static void * (*orig_malloc_hook)(const char *file, int line, size_t size); + + // check functions + // simple function declaration + void foo(); + // function declaration with parameters + char* foo(int& x, + char**y); + // simple function definition + void boo(){ + int g = 0; + }; + // check Structs + // struct + struct MyStruct{ + int sint; + }; + // typedef and elaborated types + typedef struct MyStruct myStruct; + // typedef + typedef struct{ + int ss; + } myTypedef; + // unions + union U{ + int U1; + }; + + + // check templates + // template function declaration + template + A aTemplatedFunction( B bInstance ); + // template function definition + template + A aTemplatedFunction( B bInstance ) { + A a; + return a; + } + // template method + class enclosing { + // public visibility + public: + template + A aTemplatedMethod( B bInstance ); + }; + // template class + template + class myarray { /* */ }; + // template struct + template + struct mystruct { /* */ }; + // template variable + template + char* default_alloc_template<__threads, __inst>::_S_start_free = 0; +}; + // check arrays + // arrays + int myArray [5][]; + int main(int argc, char * argv[]) + { + } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=180815 +struct bug180815 { + int i,j; +} bug180815_var0, bug180815_var1; + +// using +using Mypackage; + +// linkage spec +extern "C" { + void cfunction() {} +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CStructureCreatorTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CStructureCreatorTest.java new file mode 100644 index 00000000000..a4e522e1267 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CStructureCreatorTest.java @@ -0,0 +1,267 @@ +/******************************************************************************* + * Copyright (c) 2007 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.ui.tests.text; + +import junit.framework.TestSuite; + +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.ResourceNode; +import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; +import org.eclipse.compare.structuremergeviewer.IStructureComparator; +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.ui.tests.BaseUITestCase; + +import org.eclipse.cdt.internal.ui.compare.CStructureCreator; + +/** + * Tests for the CStructureCreator. + * + * @since 5.0 + */ +public class CStructureCreatorTest extends BaseUITestCase { + + public static TestSuite suite() { + return suite(CStructureCreatorTest.class, "_"); + } + + private ICProject fCProject; + + protected void setUp() throws Exception { + super.setUp(); + fCProject= EditorTestHelper.createCProject("CStructureCreatorTest", "resources/compare", false); + } + + protected void tearDown() throws Exception { + if (fCProject != null) { + CProjectHelper.delete(fCProject); + } + super.tearDown(); + } + + public void testStructureCreatorNodeTypes() throws Exception { + IFile file= ResourceTestHelper.findFile("/CStructureCreatorTest/src/CompareTest.cpp"); + assertNotNull(file); + CStructureCreator creator= new CStructureCreator(); + IStructureComparator node= creator.getStructure(new ResourceNode(file)); + assertNotNull(node); + Object[] children= node.getChildren(); + // one node below root == translation unit + assertEquals(1, children.length); + DocumentRangeNode tuNode= (DocumentRangeNode)children[0]; + + // tu children + children= tuNode.getChildren(); + assertEquals(10, children.length); + DocumentRangeNode child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_INCLUDE, child.getTypeCode()); + child= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_MACRO, child.getTypeCode()); + DocumentRangeNode namespace= (DocumentRangeNode)children[2]; + assertEquals(ICElement.C_NAMESPACE, namespace.getTypeCode()); + child= (DocumentRangeNode)children[3]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[4]; + assertEquals(ICElement.C_FUNCTION, child.getTypeCode()); + DocumentRangeNode struct= (DocumentRangeNode)children[5]; + assertEquals(ICElement.C_STRUCT, struct.getTypeCode()); + child= (DocumentRangeNode)children[6]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[7]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[8]; + assertEquals(ICElement.C_USING, child.getTypeCode()); + DocumentRangeNode linkageSpec= (DocumentRangeNode)children[9]; + assertEquals(ICElement.C_STORAGE_EXTERN, linkageSpec.getTypeCode()); + + // namespace children + children= namespace.getChildren(); + assertEquals(22, children.length); + DocumentRangeNode clazz= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_CLASS, clazz.getTypeCode()); + DocumentRangeNode enum1= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_ENUMERATION, enum1.getTypeCode()); + child= (DocumentRangeNode)children[2]; + assertEquals(ICElement.C_ENUMERATION, child.getTypeCode()); + child= (DocumentRangeNode)children[3]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[4]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[5]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[6]; + assertEquals(ICElement.C_VARIABLE_DECLARATION, child.getTypeCode()); + child= (DocumentRangeNode)children[7]; + assertEquals(ICElement.C_VARIABLE, child.getTypeCode()); + child= (DocumentRangeNode)children[8]; + assertEquals(ICElement.C_FUNCTION_DECLARATION, child.getTypeCode()); + child= (DocumentRangeNode)children[9]; + assertEquals(ICElement.C_FUNCTION_DECLARATION, child.getTypeCode()); + child= (DocumentRangeNode)children[10]; + assertEquals(ICElement.C_FUNCTION, child.getTypeCode()); + child= (DocumentRangeNode)children[11]; + assertEquals(ICElement.C_STRUCT, child.getTypeCode()); + child= (DocumentRangeNode)children[12]; + assertEquals(ICElement.C_TYPEDEF, child.getTypeCode()); + child= (DocumentRangeNode)children[13]; + assertEquals(ICElement.C_STRUCT, child.getTypeCode()); + child= (DocumentRangeNode)children[14]; + assertEquals(ICElement.C_TYPEDEF, child.getTypeCode()); + DocumentRangeNode union= (DocumentRangeNode)children[15]; + assertEquals(ICElement.C_UNION, union.getTypeCode()); + child= (DocumentRangeNode)children[16]; + assertEquals(ICElement.C_TEMPLATE_FUNCTION_DECLARATION, child.getTypeCode()); + child= (DocumentRangeNode)children[17]; + assertEquals(ICElement.C_TEMPLATE_FUNCTION, child.getTypeCode()); + DocumentRangeNode clazz2= (DocumentRangeNode)children[18]; + assertEquals(ICElement.C_CLASS, clazz2.getTypeCode()); + child= (DocumentRangeNode)children[19]; + assertEquals(ICElement.C_TEMPLATE_CLASS, child.getTypeCode()); + child= (DocumentRangeNode)children[20]; + assertEquals(ICElement.C_TEMPLATE_STRUCT, child.getTypeCode()); + child= (DocumentRangeNode)children[21]; + assertEquals(ICElement.C_TEMPLATE_VARIABLE, child.getTypeCode()); + + // class children + children= clazz.getChildren(); + assertEquals(3, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_FIELD, child.getTypeCode()); + child= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_METHOD, child.getTypeCode()); + namespace= (DocumentRangeNode)children[2]; + assertEquals(ICElement.C_NAMESPACE, namespace.getTypeCode()); + + // enum children + children= enum1.getChildren(); + assertEquals(3, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_ENUMERATOR, child.getTypeCode()); + child= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_ENUMERATOR, child.getTypeCode()); + child= (DocumentRangeNode)children[2]; + assertEquals(ICElement.C_ENUMERATOR, child.getTypeCode()); + + // union children + children= union.getChildren(); + assertEquals(1, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_FIELD, child.getTypeCode()); + + // enclosing class children + children= clazz2.getChildren(); + assertEquals(1, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_TEMPLATE_METHOD_DECLARATION, child.getTypeCode()); + + // nested namespace children + children= namespace.getChildren(); + assertEquals(2, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_CLASS, child.getTypeCode()); + clazz= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_CLASS, child.getTypeCode()); + // nested class children + children= clazz.getChildren(); + assertEquals(3, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_FIELD, child.getTypeCode()); + child= (DocumentRangeNode)children[1]; + assertEquals(ICElement.C_METHOD, child.getTypeCode()); + child= (DocumentRangeNode)children[2]; + assertEquals(ICElement.C_METHOD_DECLARATION, child.getTypeCode()); + + // extern "C" children + children= linkageSpec.getChildren(); + assertEquals(1, children.length); + child= (DocumentRangeNode)children[0]; + assertEquals(ICElement.C_FUNCTION, child.getTypeCode()); + } + + public void testStructureCreatorNodeSizes() throws Exception { + IFile file= ResourceTestHelper.findFile("/CStructureCreatorTest/src/CompareTest.cpp"); + assertNotNull(file); + CStructureCreator creator= new CStructureCreator(); + IStructureComparator node= creator.getStructure(new ResourceNode(file)); + assertNotNull(node); + Object[] children= node.getChildren(); + // one node below root == translation unit + assertEquals(1, children.length); + DocumentRangeNode tuNode= (DocumentRangeNode)children[0]; + IDocument document= tuNode.getDocument(); + Position range= tuNode.getRange(); + assertEqualPositions(new Position(0, document.getLength()), range); + + verifyStructure(tuNode, CoreModel.getDefault().create(file)); + } + + private void assertEqualPositions(Position expected, Position actual) { + assertEquals(expected.getOffset(), actual.getOffset()); + assertEquals(expected.getLength(), actual.getLength()); + } + + private void verifyStructure(DocumentRangeNode cNode, ICElement cElement) throws CModelException, BadLocationException { + // verify same type + assertEquals(cElement.getElementType(), cNode.getTypeCode()); + + if (cNode.getTypeCode() != ICElement.C_UNIT && cNode instanceof ITypedElement) { + Position nodeRange= cNode.getRange(); + IDocument doc= cNode.getDocument(); + ISourceReference sourceRef= (ISourceReference)cElement; + ISourceRange sourceRange= sourceRef.getSourceRange(); + // verify start and endline of elements match + assertEquals(sourceRange.getStartLine(), doc.getLineOfOffset(nodeRange.getOffset()) + 1); + assertEquals(sourceRange.getEndLine(), doc.getLineOfOffset(nodeRange.getOffset() + nodeRange.getLength() - 1) + 1); + + assertEqualPositions(new Position(sourceRange.getStartPos(), sourceRange.getLength()), nodeRange); + + if (cElement.getElementName().length() > 0) { + assertEquals(cElement.getElementName(), ((ITypedElement)cNode).getName()); + } + } + Object[] nodeChildren= cNode.getChildren(); + // merge in extern "C" children to match cmodel hierarchy + for (int i = 0; i < nodeChildren.length; i++) { + DocumentRangeNode childNode= (DocumentRangeNode)nodeChildren[i]; + if (childNode.getTypeCode() == ICElement.C_STORAGE_EXTERN) { + Object[] linkageSpecChildren= childNode.getChildren(); + Object[] newArray= new Object[nodeChildren.length - 1 + linkageSpecChildren.length]; + System.arraycopy(nodeChildren, 0, newArray, 0, i); + System.arraycopy(linkageSpecChildren, 0, newArray, i, linkageSpecChildren.length); + System.arraycopy(nodeChildren, i+1, newArray, i + linkageSpecChildren.length, nodeChildren.length - i - 1); + nodeChildren= newArray; + } + } + ICElement[] cElementChildren; + if (cElement instanceof IParent) { + cElementChildren= ((IParent)cElement).getChildren(); + } else { + cElementChildren= new ICElement[0]; + } + // verify same number of children + assertEquals(cElementChildren.length, nodeChildren.length); + for (int i = 0; i < cElementChildren.length; i++) { + verifyStructure((DocumentRangeNode)nodeChildren[i], cElementChildren[i]); + } + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java index 94e215d3071..1f7154ea0fe 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java @@ -57,5 +57,8 @@ public class TextTestSuite extends TestSuite { // word detection addTest(CWordFinderTest.suite()); + + // compare tests + addTest(CStructureCreatorTest.suite()); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties index 244e9300f21..2e750efb5da 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIMessages.properties @@ -60,25 +60,6 @@ AbstractErrorParserBlock.label.errorParsers=Error Parsers ICElementPropertyConstants.catagory=Binary Info -IndexerOptions.enableIndexing = Enable C/C++ &Indexing -IndexerOptions.problemReporting = C/C++ Index problem reporting -IndexerOptions.enablePreprocessor = Report &preprocessor problems -IndexerOptions.enableSemantic = Report &semantic problems -IndexerOptions.enableSyntactic = Report s&yntactic problems -IndexerOptiosn.task.savingAttributes = Saving Attributes - -CTagsIndexerBlock.blockName=CTags File -CTagsIndexerBlock.radioButtonInternal=Use internal CTags file (default) -CTagsIndexerBlock.radioButtonExternal=Import existing CTags file -CTagsIndexerBlock.browseButton=Browse... -CTagsIndexerBlock.fileBrowser=Select CTags File -CTagsIndexerBlock.radioButtonCTagsDefault=Use the CTags on the path (default) -CTagsIndexerBlock.radioButtonCTagsSpecified=Use the specified CTags - -CTagsIndexerBlock.ctagsLocation=CTags Location -CTagsIndexerBlock.includeGroup=Include Files -CTagsIndexerBlock.indexIncludes=Index include paths - StatusBarUpdater.num_elements_selected={0} items selected CHelpConfigurationPropertyPage.buttonLabels.CheckAll=Check All @@ -93,3 +74,4 @@ TextEditorDropAdapter.unreadableFile=Unreadable file: ''{0}'' TextEditorDropAdapter.noFile=Not a file: ''{0}'' OptionalMessageDialog_dontShowAgain= Do not show this &message again +CStructureCreatorVisitor.translationUnitName=Translation Unit diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CNode.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CNode.java index 1fd775295be..434cff31082 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CNode.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 IBM Corporation and others. + * Copyright (c) 2005, 2007 IBM Corporation 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.compare; @@ -18,20 +19,20 @@ import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.IDocument; import org.eclipse.swt.graphics.Image; + /** * */ - class CNode extends DocumentRangeNode implements ITypedElement { - public CNode(CNode parent, int type, String id, IDocument doc, int start, int length) { - super(type, id, doc, start, length); + public CNode(DocumentRangeNode parent, int type, String id, IDocument doc, int start, int length) { + super(parent, type, id, doc, start, length); if (parent != null) { parent.addChild(this); } } - public CNode(CNode parent, int type, String id, int start, int length) { + public CNode(DocumentRangeNode parent, int type, String id, int start, int length) { this(parent, type, id, parent.getDocument(), start, length); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CParseTreeBuilder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CParseTreeBuilder.java index d1b772f5683..27d8c36b0ce 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CParseTreeBuilder.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CParseTreeBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005 IBM Corporation and others. + * Copyright (c) 2005, 2007 IBM Corporation 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.compare; @@ -36,7 +37,7 @@ import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.jface.text.IDocument; /** - * + * @deprecated As of CDT 5.0. This class is not used anymore. Kept for reference only. */ public class CParseTreeBuilder extends SourceElementRequestorAdapter { @@ -295,7 +296,7 @@ public class CParseTreeBuilder extends SourceElementRequestorAdapter { } /** - * Adds a new JavaNode with the given type and name to the current container. + * Adds a new CNode with the given type and name to the current container. */ private void push(int type, String name, int declarationStart) { fStack.push(new CNode(getCurrentContainer(), type, name, declarationStart, 0)); @@ -307,12 +308,8 @@ public class CParseTreeBuilder extends SourceElementRequestorAdapter { */ private void pop(int declarationEnd) { CNode current = getCurrentContainer(); - if (current.getTypeCode() == ICElement.C_UNIT) { - current.setAppendPosition(declarationEnd + 1); - } else { - current.setAppendPosition(declarationEnd); - } - current.setLength(declarationEnd - current.getRange().getOffset() + 1); + current.setAppendPosition(declarationEnd); + current.setLength(declarationEnd - current.getRange().getOffset()); fStack.pop(); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java index 67cbc8ff2e5..1516c23e1f0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2006 IBM Corporation and others. + * Copyright (c) 2005, 2007 IBM Corporation 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 @@ -17,37 +17,43 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import org.eclipse.compare.CompareUI; -import org.eclipse.compare.IEditableContent; import org.eclipse.compare.IEncodedStreamContentAccessor; +import org.eclipse.compare.ISharedDocumentAdapter; import org.eclipse.compare.IStreamContentAccessor; -import org.eclipse.compare.structuremergeviewer.Differencer; -import org.eclipse.compare.structuremergeviewer.IDiffContainer; +import org.eclipse.compare.ResourceNode; +import org.eclipse.compare.contentmergeviewer.IDocumentRange; +import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; import org.eclipse.compare.structuremergeviewer.IStructureComparator; -import org.eclipse.compare.structuremergeviewer.IStructureCreator; +import org.eclipse.compare.structuremergeviewer.StructureCreator; +import org.eclipse.compare.structuremergeviewer.StructureRootNode; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.jface.text.Document; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.Position; -import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.dom.ICodeReaderFactory; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.CodeReader; -import org.eclipse.cdt.core.parser.IParser; -import org.eclipse.cdt.core.parser.IScanner; -import org.eclipse.cdt.core.parser.ISourceElementRequestor; -import org.eclipse.cdt.core.parser.NullLogService; -import org.eclipse.cdt.core.parser.ParserFactory; -import org.eclipse.cdt.core.parser.ParserLanguage; -import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.ParserUtil; import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.core.dom.NullCodeReaderFactory; -import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant; /** - * + * A structure creator for C/C++ translation units. */ -public class CStructureCreator implements IStructureCreator { +public class CStructureCreator extends StructureCreator { private static final String NAME = "CStructureCreator.name"; //$NON-NLS-1$ @@ -58,78 +64,18 @@ public class CStructureCreator implements IStructureCreator { return CUIPlugin.getResourceString(NAME); } - public IStructureComparator getStructure(Object input) { - - IDocument doc= CompareUI.getDocument(input); - if (doc == null) { - if (input instanceof IStreamContentAccessor) { - String s = null; - try { - s = readString((IStreamContentAccessor) input); - } catch (CoreException ex) { - } - if (s != null) { - doc = new Document(s); - new CDocumentSetupParticipant().setup(doc); - } - } - } - if (doc == null) { - return null; - } - CNode root = new CNode(null, ICElement.C_UNIT, "root", doc, 0, 0); //$NON-NLS-1$ - - ISourceElementRequestor builder = new CParseTreeBuilder(root, doc); - try { - //Using the CPP parser (was implicit before, now its explicit). If there - //are bugs while parsing C files, we might want to create a separate Structure - //compare for c files, but we'll never be completely right about .h files - IScanner scanner = - ParserFactory.createScanner(new CodeReader(doc.get().toCharArray()), new ScannerInfo(), ParserMode.QUICK_PARSE, ParserLanguage.CPP, builder, new NullLogService(), null); - IParser parser = ParserFactory.createParser(scanner, builder, ParserMode.QUICK_PARSE, ParserLanguage.CPP, ParserUtil.getParserLogService() ); - parser.parse(); - } catch (Exception e) { - // What to do when error ? - // The CParseTreeBuilder will throw CParseTreeBuilder.ParseError - // for acceptProblem. - - //TODO : New : ParserFactoryError gets thrown by ParserFactory primitives - } - - return root; - } - - public boolean canSave() { - return true; - } - - public IStructureComparator locate(Object path, Object source) { - return null; - } - - public boolean canRewriteTree() { - return false; - } - - public void rewriteTree(Differencer differencer, IDiffContainer root) { - } - - /** - * @see IStructureCreator#save - */ - public void save(IStructureComparator structure, Object input) { - if (input instanceof IEditableContent && structure instanceof CNode) { - IDocument doc = ((CNode) structure).getDocument(); - IEditableContent bca = (IEditableContent) input; - String c = doc.get(); - bca.setContent(c.getBytes()); - } - } - - /** + /* * @see IStructureCreator#getContents */ public String getContents(Object node, boolean ignoreWhitespace) { + if (node instanceof IDocumentRange) { + IDocumentRange documentRange= (IDocumentRange)node; + final Position range = documentRange.getRange(); + try { + return documentRange.getDocument().get(range.getOffset(), range.getLength()); + } catch (BadLocationException exc) { + } + } if (node instanceof IStreamContentAccessor) { IStreamContentAccessor sca = (IStreamContentAccessor) node; try { @@ -140,6 +86,80 @@ public class CStructureCreator implements IStructureCreator { return null; } + /* + * @see org.eclipse.compare.structuremergeviewer.StructureCreator#createStructureComparator(java.lang.Object, org.eclipse.jface.text.IDocument, org.eclipse.compare.ISharedDocumentAdapter, org.eclipse.core.runtime.IProgressMonitor) + */ + protected IStructureComparator createStructureComparator(Object element, + IDocument document, ISharedDocumentAdapter sharedDocumentAdapter, + IProgressMonitor monitor) throws CoreException { + + DocumentRangeNode root= new StructureRootNode(document, element, this, sharedDocumentAdapter); + + // don't follow inclusions + ICodeReaderFactory codeReaderFactory= NullCodeReaderFactory.getInstance(); + + // empty scanner info + IScannerInfo scanInfo= new ScannerInfo(); + + CodeReader reader= new CodeReader(document.get().toCharArray()); + + // determine the language + ILanguage language= determineLanguage(element); + + try { + IASTTranslationUnit ast; + ast= language.getASTTranslationUnit(reader, scanInfo, codeReaderFactory, null, ParserUtil.getParserLogService()); + CStructureCreatorVisitor structureCreator= new CStructureCreatorVisitor(root); + // build structure + ast.accept(structureCreator); + } catch (CoreException exc) { + CUIPlugin.getDefault().log(exc); + } + + return root; + } + + /** + * Try to determine the ILanguage for the given input element. + * + * @param element + * @return a language instance + */ + private ILanguage determineLanguage(Object element) { + ILanguage language= null; + if (element instanceof ResourceNode) { + IResource resource= ((ResourceNode)element).getResource(); + if (resource.getType() == IResource.FILE) { + ITranslationUnit tUnit= (ITranslationUnit)CoreModel.getDefault().create(resource); + if (tUnit != null) { + try { + language= tUnit.getLanguage(); + } catch (CoreException exc) { + // silently ignored + } + } + } + } + if (language == null) { + language= GPPLanguage.getDefault(); + } + return language; + } + + /* + * @see org.eclipse.compare.structuremergeviewer.StructureCreator#getDocumentPartitioning() + */ + protected String getDocumentPartitioning() { + return ICPartitions.C_PARTITIONING; + } + + /* + * @see org.eclipse.compare.structuremergeviewer.StructureCreator#getDocumentPartitioner() + */ + protected IDocumentPartitioner getDocumentPartitioner() { + return CUIPlugin.getDefault().getTextTools().createDocumentPartitioner(); + } + private static String readString(IStreamContentAccessor sa) throws CoreException { InputStream is= sa.getContents(); if (is != null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreatorVisitor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreatorVisitor.java new file mode 100644 index 00000000000..0ed50e5b8dc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreatorVisitor.java @@ -0,0 +1,542 @@ +/******************************************************************************* + * Copyright (c) 2007 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.compare; + +import java.util.Stack; + +import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; +import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisiblityLabel; +import org.eclipse.cdt.core.model.ICElement; + +import org.eclipse.cdt.internal.core.model.ASTStringUtil; +import org.eclipse.cdt.internal.core.model.CoreModelMessages; + +import org.eclipse.cdt.internal.ui.CUIMessages; + +/** + * AST visitor to create compare structure. + * + * @since 5.0 + */ +class CStructureCreatorVisitor extends CPPASTVisitor { + + private static final String TRANSLATION_UNIT_NAME = CUIMessages.getString("CStructureCreatorVisitor.translationUnitName"); //$NON-NLS-1$ + private static final String ANONYMOUS_NAME= CoreModelMessages.getString("CElementLabels.anonymous"); //$NON-NLS-1$ + + private Stack fStack = new Stack(); + private IDocument fDocument; + private String fTranslationUnitFileName; + + /** + * Create visitor adding nodes to given root. + * + * @param root + */ + public CStructureCreatorVisitor(DocumentRangeNode root) { + fDocument = root.getDocument(); + fStack.clear(); + fStack.push(root); + // visitor options + shouldVisitTranslationUnit= true; + shouldVisitDeclarations= true; + shouldVisitEnumerators=true; + shouldVisitNamespaces=true; + } + + /* + * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit) + */ + public int visit(IASTTranslationUnit tu) { + fTranslationUnitFileName= tu.getFilePath(); + + push(ICElement.C_UNIT, TRANSLATION_UNIT_NAME, 0); + + // TODO fix ordering of includes and macros + // includes + final IASTPreprocessorIncludeStatement[] includeDirectives= tu.getIncludeDirectives(); + for (int i= 0; i < includeDirectives.length; i++) { + IASTPreprocessorIncludeStatement includeDirective= includeDirectives[i]; + if (isLocalToFile(includeDirective)) { + push(ICElement.C_INCLUDE, new String(includeDirective.getName().toCharArray()), getStartOffset(includeDirective)); + pop(getEndOffset(includeDirective)); + } + } + // macros + final IASTPreprocessorMacroDefinition[] macroDefinitions= tu.getMacroDefinitions(); + for (int i= 0; i < macroDefinitions.length; i++) { + IASTPreprocessorMacroDefinition macroDefinition= macroDefinitions[i]; + if (isLocalToFile(macroDefinition)) { + push(ICElement.C_MACRO, new String(macroDefinition.getName().toCharArray()), getStartOffset(macroDefinition)); + pop(getEndOffset(macroDefinition)); + } + } + + return super.visit(tu); + } + + /** + * Test whether given AST node is local to the source file + * and not part of an inclusion. + * + * @param node + * @return true if the node is part of the source file. + */ + private boolean isLocalToFile(IASTNode node) { + return fTranslationUnitFileName.equals(node.getContainingFilename()); + } + + /** + * Compute the start offset of given AST node. + * + * @param node + * @return + */ + private int getStartOffset(IASTNode node) { + IASTFileLocation fileLocation= getMinFileLocation(node.getNodeLocations()); + if (fileLocation != null) { + return fileLocation.getNodeOffset(); + } + DocumentRangeNode container= getCurrentContainer(); + Object[] children= container.getChildren(); + if (children != null && children.length > 0) { + Position prevRange= ((DocumentRangeNode)children[children.length - 1]).getRange(); + return prevRange.getOffset() + prevRange.getLength(); + } + // fallback: use container range start + Position containerRange= container.getRange(); + return containerRange.getOffset(); + } + + /** + * Compute the end offset of give AST node. + * + * @param node + * @return + */ + private int getEndOffset(IASTNode node) { + IASTFileLocation fileLocation= getMaxFileLocation(node.getNodeLocations()); + if (fileLocation != null) { + return fileLocation.getNodeOffset() + fileLocation.getNodeLength(); + } + // fallback: use container range end + DocumentRangeNode container= getCurrentContainer(); + Position containerRange= container.getRange(); + return containerRange.getOffset() + containerRange.getLength(); + } + +/* + * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#leave(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit) + */ + public int leave(IASTTranslationUnit tu) { + super.leave(tu); + assert getCurrentContainer().getTypeCode() == ICElement.C_UNIT; + pop(fDocument.getLength()); + return PROCESS_SKIP; + } + + /* + * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclaration) + */ + public int visit(IASTDeclaration node) { + boolean isTemplateDecl= isTemplateDecl(node); + final int startOffset= isTemplateDecl ? getStartOffset(node.getParent()) : getStartOffset(node); + final int endOffset= getEndOffset(node); + if (node instanceof IASTFunctionDefinition) { + IASTFunctionDefinition functionDef= (IASTFunctionDefinition)node; + final int nodeType; + if (inClassBody()) { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_METHOD : ICElement.C_METHOD; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_FUNCTION : ICElement.C_FUNCTION; + } + push(nodeType, getDeclaratorName(functionDef.getDeclarator()), startOffset); + pop(endOffset); + return PROCESS_SKIP; + } else if (node instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration simpleDecl= (IASTSimpleDeclaration)node; + IASTDeclSpecifier declSpec= simpleDecl.getDeclSpecifier(); + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + ICPPASTCompositeTypeSpecifier compositeTypeSpec= (ICPPASTCompositeTypeSpecifier)declSpec; + final String nodeName= getTypeName(compositeTypeSpec); + final int nodeType; + switch (compositeTypeSpec.getKey()) { + case IASTCompositeTypeSpecifier.k_struct: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_STRUCT : ICElement.C_STRUCT; + break; + case IASTCompositeTypeSpecifier.k_union: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_UNION : ICElement.C_UNION; + break; + case ICPPASTCompositeTypeSpecifier.k_class: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_CLASS : ICElement.C_CLASS; + break; + default: + assert false : "Unexpected composite type specifier"; //$NON-NLS-1$ + return PROCESS_CONTINUE; + } + push(nodeType, nodeName, startOffset); + } else if (declSpec instanceof IASTEnumerationSpecifier) { + IASTEnumerationSpecifier enumSpecifier= (IASTEnumerationSpecifier)declSpec; + push(ICElement.C_ENUMERATION, getEnumerationName(enumSpecifier), startOffset); + } else { + IASTDeclarator[] declarators= simpleDecl.getDeclarators(); + for (int i = 0; i < declarators.length; i++) { + IASTDeclarator declarator= declarators[i]; + int declStartOffset= declarators.length == 1 ? startOffset : getStartOffset(declarator); + int declEndOffset= declarators.length == 1 ? endOffset : getEndOffset(declarator); + final String nodeName = getDeclaratorName(declarator); + if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_typedef) { + push(ICElement.C_TYPEDEF, nodeName, declStartOffset); + pop(declEndOffset); + } else if (declarator instanceof IASTFunctionDeclarator && !hasNestedPointerOperators(declarator)) { + final int nodeType; + if (inClassBody()) { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_METHOD_DECLARATION : ICElement.C_METHOD_DECLARATION; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_FUNCTION_DECLARATION : ICElement.C_FUNCTION_DECLARATION; + } + push(nodeType, nodeName, declStartOffset); + pop(declEndOffset); + } else if (declarator != null) { + final int nodeType; + if (inClassBody()) { + nodeType= ICElement.C_FIELD; + } else { + if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) { + nodeType= ICElement.C_VARIABLE_DECLARATION; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_VARIABLE : ICElement.C_VARIABLE; + } + } + push(nodeType, nodeName, declStartOffset); + pop(declEndOffset); + } + } + } + } else if (node instanceof IASTASMDeclaration) { + // ignored + } else if (node instanceof ICPPASTVisiblityLabel) { + // ignored + } else if (node instanceof ICPPASTNamespaceDefinition) { + // handled below + } else if (node instanceof ICPPASTNamespaceAlias) { + // ignored + } else if (node instanceof ICPPASTUsingDeclaration) { + ICPPASTUsingDeclaration usingDecl= (ICPPASTUsingDeclaration)node; + push(ICElement.C_USING, ASTStringUtil.getQualifiedName(usingDecl.getName()), startOffset); + pop(endOffset); + } else if (node instanceof ICPPASTUsingDirective) { + ICPPASTUsingDirective usingDirective= (ICPPASTUsingDirective)node; + push(ICElement.C_USING, ASTStringUtil.getQualifiedName(usingDirective.getQualifiedName()), startOffset); + pop(endOffset); + } else if (node instanceof ICPPASTLinkageSpecification) { + ICPPASTLinkageSpecification linkageSpec= (ICPPASTLinkageSpecification)node; + push(ICElement.C_STORAGE_EXTERN, "extern \"" + linkageSpec.getLiteral() + '"', startOffset); //$NON-NLS-1$ + } else if (node instanceof ICPPASTTemplateDeclaration) { + // handled at child declaration level + } else if (node instanceof ICPPASTTemplateSpecialization) { + // ignored + } else if (node instanceof ICPPASTExplicitTemplateInstantiation) { + // ignored + } else if (node instanceof IASTProblemDeclaration) { + // ignored + } + return super.visit(node); + } + + /* + * @see org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor#visit(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition) + */ + public int visit(ICPPASTNamespaceDefinition namespace) { + push(ICElement.C_NAMESPACE, ASTStringUtil.getQualifiedName(namespace.getName()), getStartOffset(namespace)); + return super.visit(namespace); + } + + /* + * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator) + */ + public int visit(IASTEnumerator enumerator) { + push(ICElement.C_ENUMERATOR, ASTStringUtil.getQualifiedName(enumerator.getName()), getStartOffset(enumerator)); + pop(getEndOffset(enumerator)); + return super.visit(enumerator); + } + + /* + * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#leave(org.eclipse.cdt.core.dom.ast.IASTDeclaration) + */ + public int leave(IASTDeclaration node) { + super.leave(node); + boolean isTemplateDecl= isTemplateDecl(node); + final int endOffset= isTemplateDecl ? getEndOffset(node.getParent()) : getEndOffset(node); + if (node instanceof IASTFunctionDefinition) { + final int nodeType; + if (inClassBody()) { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_METHOD : ICElement.C_METHOD; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_FUNCTION : ICElement.C_FUNCTION; + } + assert getCurrentContainer().getTypeCode() == nodeType; + pop(endOffset); + } else if (node instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration simpleDecl= (IASTSimpleDeclaration)node; + IASTDeclSpecifier declSpec= simpleDecl.getDeclSpecifier(); + boolean isCompositeType= false; + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + isCompositeType= true; + ICPPASTCompositeTypeSpecifier compositeTypeSpec= (ICPPASTCompositeTypeSpecifier)declSpec; + final int nodeType; + switch (compositeTypeSpec.getKey()) { + case IASTCompositeTypeSpecifier.k_struct: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_STRUCT : ICElement.C_STRUCT; + break; + case IASTCompositeTypeSpecifier.k_union: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_UNION : ICElement.C_UNION; + break; + case ICPPASTCompositeTypeSpecifier.k_class: + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_CLASS : ICElement.C_CLASS; + break; + default: + assert false : "Unexpected composite type specifier"; //$NON-NLS-1$ + return PROCESS_CONTINUE; + } + assert getCurrentContainer().getTypeCode() == nodeType; + pop(isTemplateDecl ? endOffset : getEndOffset(declSpec)); + } else if (declSpec instanceof IASTEnumerationSpecifier) { + isCompositeType= true; + assert getCurrentContainer().getTypeCode() == ICElement.C_ENUMERATION; + pop(getEndOffset(declSpec)); + } + if (isCompositeType) { + IASTDeclarator[] declarators= simpleDecl.getDeclarators(); + for (int i= 0; i < declarators.length; i++) { + IASTDeclarator declarator= declarators[i]; + final String nodeName= getDeclaratorName(declarator); + final int declStartOffset= getStartOffset(declarator); + final int declEndOffset= getEndOffset(declarator); + if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_typedef) { + push(ICElement.C_TYPEDEF, nodeName, declStartOffset); + pop(declEndOffset); + } else if (declarator instanceof IASTFunctionDeclarator && !hasNestedPointerOperators(declarator)) { + final int nodeType; + if (inClassBody()) { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_METHOD_DECLARATION : ICElement.C_METHOD_DECLARATION; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_FUNCTION_DECLARATION : ICElement.C_FUNCTION_DECLARATION; + } + push(nodeType, nodeName, declStartOffset); + pop(declEndOffset); + } else if (declarator != null) { + final int nodeType; + if (inClassBody()) { + nodeType= ICElement.C_FIELD; + } else { + if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) { + nodeType= ICElement.C_VARIABLE_DECLARATION; + } else { + nodeType= isTemplateDecl ? ICElement.C_TEMPLATE_VARIABLE : ICElement.C_VARIABLE; + } + } + push(nodeType, nodeName, declStartOffset); + pop(declEndOffset); + } + } + } + } else if (node instanceof IASTASMDeclaration) { + // ignored + } else if (node instanceof ICPPASTVisiblityLabel) { + // ignored + } else if (node instanceof ICPPASTNamespaceDefinition) { + // handled below + } else if (node instanceof ICPPASTNamespaceAlias) { + // ignored + } else if (node instanceof ICPPASTUsingDeclaration) { + // handled in visit + } else if (node instanceof ICPPASTUsingDirective) { + // handled in visit + } else if (node instanceof ICPPASTLinkageSpecification) { + assert getCurrentContainer().getTypeCode() == ICElement.C_STORAGE_EXTERN; + pop(endOffset); + } else if (node instanceof ICPPASTTemplateDeclaration) { + // handled at child declaration level + } else if (node instanceof ICPPASTTemplateSpecialization) { + // ignored + } else if (node instanceof ICPPASTExplicitTemplateInstantiation) { + // ignored + } else if (node instanceof IASTProblemDeclaration) { + // ignored + } + return PROCESS_CONTINUE; + } + + /* + * @see org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor#leave(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition) + */ + public int leave(ICPPASTNamespaceDefinition namespace) { + assert getCurrentContainer().getTypeCode() == ICElement.C_NAMESPACE; + pop(getEndOffset(namespace)); + return super.leave(namespace); + } + + private DocumentRangeNode getCurrentContainer() { + return (DocumentRangeNode) fStack.peek(); + } + + /** + * Adds a new node with the given type and name to the current container. + */ + private void push(int type, String name, int declarationStart) { + if (name.length() == 0) { + name= ANONYMOUS_NAME; + } + fStack.push(new CNode(getCurrentContainer(), type, name, declarationStart, 0)); + } + + /** + * Closes the current node by setting its end position + * and pops it off the stack. + */ + private void pop(int declarationEnd) { + DocumentRangeNode current= getCurrentContainer(); + current.setAppendPosition(declarationEnd); + current.setLength(declarationEnd - current.getRange().getOffset()); + fStack.pop(); + } + + + /** + * @return true if the current container is class-like. + */ + private boolean inClassBody() { + int typeCode= getCurrentContainer().getTypeCode(); + return typeCode == ICElement.C_CLASS + || typeCode == ICElement.C_TEMPLATE_CLASS + || typeCode == ICElement.C_STRUCT + || typeCode == ICElement.C_TEMPLATE_STRUCT + || typeCode == ICElement.C_UNION + || typeCode == ICElement.C_TEMPLATE_UNION; + } + + /** + * Test whether the given declaration is a templated declaration. + * + * @param node + * @return true if the declaration is templated. + */ + private boolean isTemplateDecl(IASTDeclaration node) { + return node.getParent() instanceof ICPPASTTemplateDeclaration; + } + + private boolean hasNestedPointerOperators(IASTDeclarator declarator) { + declarator= declarator.getNestedDeclarator(); + while (declarator != null) { + if (declarator.getPointerOperators().length > 0) { + return true; + } + declarator= declarator.getNestedDeclarator(); + } + return false; + } + + private String getEnumerationName(IASTEnumerationSpecifier enumSpecifier) { + String nodeName= ASTStringUtil.getQualifiedName(enumSpecifier.getName()); + if (nodeName.length() == 0) { + nodeName= ANONYMOUS_NAME; + } + return nodeName; + } + + private String getTypeName(IASTCompositeTypeSpecifier compositeTypeSpec) { + String nodeName= ASTStringUtil.getQualifiedName(compositeTypeSpec.getName()); + if (nodeName.length() == 0) { + nodeName= ANONYMOUS_NAME; + } + return nodeName; + } + + private String getDeclaratorName(IASTDeclarator node) { + node= getInnermostDeclarator(node); + IASTName name= node.getName(); + String nodeName= ASTStringUtil.getQualifiedName(name); + if (nodeName.length() == 0) { + nodeName= ANONYMOUS_NAME; + } + return nodeName; + } + + private IASTDeclarator getInnermostDeclarator(IASTDeclarator node) { + IASTDeclarator nested= node.getNestedDeclarator(); + while (nested != null) { + node= nested; + nested= node.getNestedDeclarator(); + } + return node; + } + + private static IASTFileLocation getMaxFileLocation(IASTNodeLocation[] locations) { + if (locations == null || locations.length == 0) { + return null; + } + final IASTNodeLocation nodeLocation= locations[locations.length-1]; + if (nodeLocation instanceof IASTFileLocation) { + return (IASTFileLocation)nodeLocation; + } else if (nodeLocation instanceof IASTMacroExpansion) { + IASTNodeLocation[] macroLocations= ((IASTMacroExpansion)nodeLocation).getExpansionLocations(); + return getMaxFileLocation(macroLocations); + } + return null; + } + + private static IASTFileLocation getMinFileLocation(IASTNodeLocation[] locations) { + if (locations == null || locations.length == 0) { + return null; + } + final IASTNodeLocation nodeLocation= locations[0]; + if (nodeLocation instanceof IASTFileLocation) { + return (IASTFileLocation)nodeLocation; + } else if (nodeLocation instanceof IASTMacroExpansion) { + IASTNodeLocation[] macroLocations= ((IASTMacroExpansion)nodeLocation).getExpansionLocations(); + return getMinFileLocation(macroLocations); + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/SourceElementRequestorAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/SourceElementRequestorAdapter.java index 03121975df2..09436afa430 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/SourceElementRequestorAdapter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/SourceElementRequestorAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2006 QNX Software Systems and others. + * Copyright (c) 2002, 2007 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -54,7 +54,7 @@ import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.cdt.core.parser.ast.IASTVariableReference; /** - * + * @deprecated As of CDT 5.0. This class is not used anymore. Kept for reference only. */ public class SourceElementRequestorAdapter implements ISourceElementRequestor { /* (non-Javadoc)