diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SelectionParseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SelectionParseTest.java index 330f5b3a067..0c1dd6a8036 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SelectionParseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SelectionParseTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2008 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 @@ -64,11 +64,11 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = "void f() { int x; x=3; }"; //$NON-NLS-1$ int offset1 = code.indexOf( "x=" ); //$NON-NLS-1$ int length = "x".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, offset1, length ); + IASTNode node = parse( code, ParserLanguage.C, offset1, length ).getParent(); assertNotNull(node); assertTrue( node instanceof IASTIdExpression ); assertEquals(((IASTIdExpression)node).getName().toString(), "x"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, offset1, length ); + node = parse( code, ParserLanguage.CPP, offset1, length ).getParent(); assertNotNull(node); assertTrue( node instanceof IASTIdExpression ); assertEquals(((IASTIdExpression)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -83,7 +83,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = "int x(){x( );}"; //$NON-NLS-1$ int offset1 = code.indexOf( "x( " ); //$NON-NLS-1$ int length = "x".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, offset1, length ); + IASTNode node = parse( code, ParserLanguage.C, offset1, length ).getParent(); assertNotNull(node); assertTrue( node instanceof IASTIdExpression ); assertEquals(((IASTIdExpression)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -91,7 +91,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IFunction); assertEquals(((IFunction)name.resolveBinding()).getName(), "x"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, offset1, length ); + node = parse( code, ParserLanguage.CPP, offset1, length ).getParent(); assertNotNull(node); assertTrue( node instanceof IASTIdExpression ); assertEquals(((IASTIdExpression)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -184,7 +184,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = "int main( int argc ) { int x = argc; }"; //$NON-NLS-1$ int offset1 = code.indexOf( "argc;" ); //$NON-NLS-1$ int length = "argc".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, offset1, length ); + IASTNode node = parse( code, ParserLanguage.C, offset1, length ).getParent().getParent(); assertNotNull(node); assertTrue( node instanceof IASTInitializerExpression ); assertEquals( ((IASTIdExpression)((IASTInitializerExpression)node).getExpression()).getName().toString(), "argc" ); //$NON-NLS-1$ @@ -192,7 +192,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IParameter); assertEquals(((IParameter)name.resolveBinding()).getName(), "argc"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, offset1, length ); + node = parse( code, ParserLanguage.CPP, offset1, length ).getParent().getParent(); assertNotNull(node); assertTrue( node instanceof IASTInitializerExpression ); assertEquals( ((IASTIdExpression)((IASTInitializerExpression)node).getExpression()).getName().toString(), "argc" ); //$NON-NLS-1$ @@ -357,6 +357,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { { case 0: case 1: + node= node.getParent().getParent(); assertTrue(node instanceof IASTTypeId); assertEquals(((IASTNamedTypeSpecifier)((IASTTypeId)node).getDeclSpecifier()).getName().toString(), "Gonzo"); //$NON-NLS-1$ name = ((IASTNamedTypeSpecifier)((IASTTypeId)node).getDeclSpecifier()).getName(); @@ -425,7 +426,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int startIndex = code.indexOf( "foo(1)"); //$NON-NLS-1$ int length = "foo".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.C, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "foo"); //$NON-NLS-1$ @@ -433,7 +434,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IFunction); assertEquals(((IFunction)name.resolveBinding()).getName(), "foo"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, startIndex, length ); + node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "foo"); //$NON-NLS-1$ @@ -466,7 +467,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertTrue(name.resolveBinding() instanceof IEnumeration); assertEquals(((IEnumeration)name.resolveBinding()).getName(), "EColours"); //$NON-NLS-1$ startIndex = codeCPP.indexOf( "EColours color"); //$NON-NLS-1$ - node = parse( codeCPP, ParserLanguage.CPP, startIndex, length ); + node = parse( codeCPP, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTNamedTypeSpecifier); assertEquals(((IASTNamedTypeSpecifier)node).getName().toString(), "EColours"); //$NON-NLS-1$ @@ -519,7 +520,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int startIndex = code.indexOf( "static_function( file )"); //$NON-NLS-1$ int length = "static_function".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.C, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "static_function"); //$NON-NLS-1$ @@ -527,7 +528,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IFunction); assertEquals(((IFunction)name.resolveBinding()).getName(), "static_function"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, startIndex, length ); + node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "static_function"); //$NON-NLS-1$ @@ -569,7 +570,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { int startIndex = code.indexOf( "/**/fprintf") + 4; //$NON-NLS-1$ int length = "fprintf".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.C, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "fprintf"); //$NON-NLS-1$ @@ -577,7 +578,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IFunction); assertEquals(((IFunction)name.resolveBinding()).getName(), "fprintf"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, startIndex, length ); + node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "fprintf"); //$NON-NLS-1$ @@ -614,7 +615,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertTrue(name.resolveBinding() instanceof ICompositeType); assertEquals(((ICompositeType)name.resolveBinding()).getName(), "Squaw"); //$NON-NLS-1$ startIndex = codeCPP.indexOf( "sizeof( ") + "sizeof( ".length(); //$NON-NLS-1$ //$NON-NLS-2$ - node = parse( codeCPP, ParserLanguage.CPP, startIndex, length ); + node = parse( codeCPP, ParserLanguage.CPP, startIndex, length ).getParent().getParent(); assertNotNull(node); assertTrue(node instanceof IASTTypeId); assertEquals(((IASTNamedTypeSpecifier)((IASTTypeId)node).getDeclSpecifier()).getName().toString(), "Squaw"); //$NON-NLS-1$ @@ -638,7 +639,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int startIndex = code.indexOf( "return ") + "return ".length(); //$NON-NLS-1$ //$NON-NLS-2$ int length = "FOUND_ME".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "FOUND_ME"); //$NON-NLS-1$ @@ -739,7 +740,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int startIndex = code.indexOf( "new B" ) + 4; //$NON-NLS-1$ int length = "B".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent().getParent(); assertNotNull(node); assertTrue(node instanceof IASTTypeId); assertEquals(((IASTNamedTypeSpecifier)((IASTTypeId)node).getDeclSpecifier()).getName().toString(), "B"); //$NON-NLS-1$ @@ -758,7 +759,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int startIndex = code.indexOf( "(A*)" ) + 1; //$NON-NLS-1$ int length = "A".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ); + IASTNode node = parse( code, ParserLanguage.CPP, startIndex, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTNamedTypeSpecifier); assertEquals(((IASTNamedTypeSpecifier)node).getName().toString(), "A"); //$NON-NLS-1$ @@ -845,7 +846,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { index = code.indexOf( "Card( int rank );") + 10; //$NON-NLS-1$ length = "rank".length(); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "rank"); //$NON-NLS-1$ @@ -855,7 +856,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertEquals(((IVariable)name.resolveBinding()).getName(), "rank"); //$NON-NLS-1$ index = code.indexOf( "int rank;") + 4; //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "rank"); //$NON-NLS-1$ @@ -898,7 +899,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { index = code.indexOf( "Card::Card( int rank )") + 16; //$NON-NLS-1$ length = "rank".length(); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "rank"); //$NON-NLS-1$ @@ -958,7 +959,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertEquals(((ICPPField)name.resolveBinding()).getName(), "rank"); //$NON-NLS-1$ index = code.indexOf( "this->rank = rank;") + 13; //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "rank"); //$NON-NLS-1$ @@ -999,7 +1000,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { index = code.indexOf( "this->rank = getRank();") + 13; //$NON-NLS-1$ length = "getRank".length(); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTIdExpression); assertEquals(((IASTIdExpression)node).getName().toString(), "getRank"); //$NON-NLS-1$ @@ -1037,7 +1038,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = writer.toString(); int index = code.indexOf( "void f(int itself){}") + 11; //$NON-NLS-1$ int length = "itself".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, index, length ); + IASTNode node = parse( code, ParserLanguage.C, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "itself"); //$NON-NLS-1$ @@ -1045,7 +1046,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { assertNotNull(name.resolveBinding()); assertTrue(name.resolveBinding() instanceof IVariable); assertEquals(((IVariable)name.resolveBinding()).getName(), "itself"); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "itself"); //$NON-NLS-1$ @@ -1119,7 +1120,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = buffer.toString(); int index = code.indexOf("x;"); //$NON-NLS-1$ int length = "x".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ); + IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -1138,7 +1139,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = buffer.toString(); int index = code.indexOf("x;"); //$NON-NLS-1$ int length = "x".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ); + IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -1177,7 +1178,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = buffer.toString(); int index = code.indexOf("y;"); //$NON-NLS-1$ int length = "y".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ); + IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "y"); //$NON-NLS-1$ @@ -1198,7 +1199,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = buffer.toString(); int index = code.indexOf("c x;"); //$NON-NLS-1$ int length = "c".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ); + IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTNamedTypeSpecifier); assertEquals(((IASTNamedTypeSpecifier)node).getName().toString(), "c"); //$NON-NLS-1$ @@ -1209,7 +1210,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { index = code.indexOf("x;"); //$NON-NLS-1$ length = "x".length(); //$NON-NLS-1$ - node = parse( code, ParserLanguage.C, true, true, index, length ); + node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "x"); //$NON-NLS-1$ @@ -1308,7 +1309,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { String code = buffer.toString(); int index = code.indexOf("b,a"); //$NON-NLS-1$ int length = "b".length(); //$NON-NLS-1$ - IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ); + IASTNode node = parse( code, ParserLanguage.C, true, true, index, length ).getParent(); assertNotNull(node); assertTrue(node instanceof IASTDeclarator); IASTName name = ((IASTDeclarator)node).getName(); @@ -1518,7 +1519,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { index = code.indexOf("c;"); //$NON-NLS-1$ length = "c".length(); //$NON-NLS-1$ - node = parse( code, ParserLanguage.CPP, index, length ); + node = parse( code, ParserLanguage.CPP, index, length ).getParent(); assertNotNull(node); assertTrue( node instanceof IASTDeclarator); assertEquals(((IASTDeclarator)node).getName().toString(), "c"); //$NON-NLS-1$ @@ -1648,7 +1649,7 @@ public class AST2SelectionParseTest extends AST2SelectionParseBaseTest { public void testBug86126() throws Exception { String header= "foo"+System.currentTimeMillis()+".h"; String source= "blah"+System.currentTimeMillis()+".c"; - importFile(header, "int x;\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ + importFile(header, "int x;\r\n"); //$NON-NLS-1$ String code = "#include \""+header+"\"\r\n"; //$NON-NLS-1$ IFile file = importFile(source, code); int offset1 = code.indexOf( "#include \""+header+"\"" ); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTNodeSelectorTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTNodeSelectorTest.java new file mode 100644 index 00000000000..7b456299882 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/ASTNodeSelectorTest.java @@ -0,0 +1,372 @@ +/******************************************************************************* + * Copyright (c) 2008 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.core.parser.tests.ast2; + +import java.io.IOException; + +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; + +public class ASTNodeSelectorTest extends AST2BaseTest { + + static public TestSuite suite() { + return suite(ASTNodeSelectorTest.class); + } + + private String fCode; + private IASTTranslationUnit fTu; + private IASTNodeSelector fSelector; + + public ASTNodeSelectorTest() { + } + + public ASTNodeSelectorTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + createTranslationUnit(); + } + + private void createTranslationUnit() throws IOException { + fCode= getContents(1)[0].toString(); + CodeReader codeReader = new CodeReader(fCode.toCharArray()); + ScannerInfo scannerInfo = new ScannerInfo(); + IScanner scanner= AST2BaseTest.createScanner(codeReader, ParserLanguage.CPP, ParserMode.COMPLETE_PARSE, scannerInfo, false); + GNUCPPSourceParser parser= new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, new NullLogService(), new GPPParserExtensionConfiguration()); + fTu= parser.parse(); + fSelector= fTu.getNodeSelector(null); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + private void testContainedName(int from, int to, String sig) { + IASTName name= fSelector.findFirstContainedName(from, to-from); + verify(sig, name); + } + + private void verify(String sig, IASTNode node) { + if (sig == null) { + assertNull("unexpexted selection: " + (node == null ? "" : node.getRawSignature()), node); + } + else { + assertNotNull("unable to select " + sig, node); + if (node instanceof IASTName) { + assertEquals(sig, ((IASTName) node).toString()); + } + else { + assertEquals(sig, node.getRawSignature()); + } + } + } + + private void testContainedNode(int from, int to, String sig) { + IASTNode node= fSelector.findFirstContainedNode(from, to-from); + verify(sig, node); + } + + private void testName(int from, int to, String sig) { + IASTName name= fSelector.findName(from, to-from); + verify(sig, name); + } + + private void testNode(int from, int to, String sig) { + IASTNode node= fSelector.findNode(from, to-from); + verify(sig, node); + } + + private void testEnclosingName(int from, int to, String sig) { + IASTName name= fSelector.findEnclosingName(from, to-from); + verify(sig, name); + } + + private void testEnclosingNode(int from, int to, String sig) { + IASTNode node= fSelector.findEnclosingNode(from, to-from); + verify(sig, node); + } + + private void testExpansion(int from, int to, String sig) { + IASTPreprocessorMacroExpansion exp= fSelector.findEnclosingMacroExpansion(from, to-from); + verify(sig, exp); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #include + // int a; + public void testInclusion() { + int include_start= fCode.indexOf("#include"); + int name_start= fCode.indexOf("test"); + int include_end= fCode.indexOf(">") + 1; + + testContainedName(include_start-1, include_end+1, "test"); + testContainedName(name_start, include_end, "test"); + testContainedName(include_start+1, name_start+1, null); + testContainedName(name_start+1, name_start+7, null); + + testContainedNode(include_start-1, include_end+1, "#include "); + testContainedNode(name_start, include_end, "test"); + testContainedNode(include_start+1, name_start+1, null); + testContainedNode(name_start+1, name_start+7, null); + + testEnclosingName(name_start, name_start+4, "test"); + testEnclosingName(name_start, name_start, "test"); + testEnclosingName(name_start+4, name_start+4, "test"); + testEnclosingName(name_start-1, name_start+1, null); + testEnclosingName(name_start+4, name_start+5, null); + + testEnclosingNode(name_start, name_start+4, "test"); + testEnclosingNode(name_start, name_start, "test"); + testEnclosingNode(name_start+4, name_start+4, "test"); + testEnclosingNode(name_start-1, name_start+1, "#include "); + testEnclosingNode(name_start+4-1, name_start+4+1, "#include "); + + testExpansion(name_start, name_start+4, null); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define EMPTY + // #define TEST_H "test.h" + // void func() { + // #include EMPTY TEST_H + // } + public void testInclusionWithExpansions() { + int inclusion_start= fCode.indexOf("#include"); + int empty_start= fCode.indexOf("EMPTY", inclusion_start); + int testh_start= fCode.indexOf("TEST_H", empty_start); + int file_end= fCode.length(); + + testContainedName(inclusion_start-1, file_end-1, "EMPTY"); + testContainedName(testh_start, file_end, "TEST_H"); + testContainedName(testh_start+1, file_end, null); + testContainedName(testh_start, testh_start+5, null); + + testContainedNode(inclusion_start-1, file_end+1, "#include EMPTY TEST_H"); + testContainedNode(testh_start, file_end, "TEST_H"); + testContainedNode(testh_start+1, file_end, null); + testContainedNode(testh_start, testh_start+5, null); + + testName(empty_start, empty_start+5, "EMPTY"); + testName(empty_start-1, empty_start+5, null); + testName(empty_start+1, empty_start+5, null); + testName(empty_start, empty_start+4, null); + testName(empty_start, empty_start+6, null); + + testNode(empty_start, empty_start+5, "EMPTY"); + testNode(empty_start-1, empty_start+5, null); + testNode(empty_start+1, empty_start+5, null); + testNode(empty_start, empty_start+4, null); + testNode(empty_start, empty_start+6, null); + + testEnclosingName(empty_start, empty_start+5, "EMPTY"); + testEnclosingName(empty_start, empty_start, "EMPTY"); + testEnclosingName(empty_start+5, empty_start+5, "EMPTY"); + testEnclosingName(empty_start-1, empty_start, null); + testEnclosingName(empty_start+5, empty_start+6, "test.h"); + testEnclosingName(testh_start, testh_start+6, "TEST_H"); + testEnclosingName(testh_start, testh_start, "TEST_H"); + testEnclosingName(testh_start+6, testh_start+6, "TEST_H"); + testEnclosingName(testh_start-1, testh_start+1, "test.h"); + testEnclosingName(testh_start+5, testh_start+7, null); + + testEnclosingNode(empty_start, empty_start+5, "EMPTY"); + testEnclosingNode(empty_start, empty_start, "EMPTY"); + testEnclosingNode(empty_start+5, empty_start+5, "EMPTY"); + testEnclosingNode(empty_start-1, empty_start, "#include EMPTY TEST_H"); + testEnclosingNode(empty_start+5, empty_start+6, "test.h"); + testEnclosingNode(testh_start, testh_start+6, "TEST_H"); + testEnclosingNode(testh_start, testh_start, "TEST_H"); + testEnclosingNode(testh_start+6, testh_start+6, "TEST_H"); + testEnclosingNode(testh_start-1, testh_start+1, "test.h"); + testEnclosingNode(testh_start+6-1, testh_start+6+1, "{\n #include EMPTY TEST_H\n }"); + + testExpansion(empty_start, empty_start+5, "EMPTY"); + testExpansion(empty_start, empty_start, "EMPTY"); + testExpansion(empty_start+5, empty_start+5, "EMPTY"); + testExpansion(empty_start-1, empty_start, null); + testExpansion(empty_start+5, empty_start+6, null); + testExpansion(testh_start, testh_start+6, "TEST_H"); + } + + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define xx 1 + // #if xx == 2 + // #elif xx == 1 + // #endif + public void testMacroInConditionalExpression() { + int x1= fCode.indexOf("xx"); + int x2= fCode.indexOf("xx", x1+1); + int x3= fCode.indexOf("xx", x2+1); + + testContainedName(x1, x1+2, "xx"); + testContainedName(x2-1, x2+2, "xx"); + testContainedName(x3, x3+3, "xx"); + testContainedName(x1, x1+1, null); + testContainedName(x2+1, x2+2, null); + testContainedName(x3+1, x3+1, null); + + testName(x1, x1+2, "xx"); + testName(x2, x2+2, "xx"); + testName(x3, x3+2, "xx"); + testName(x1+1, x1+2, null); + testName(x2-1, x2+2, null); + testName(x3, x3+3, null); + testName(x3, x3+1, null); + + testEnclosingName(x1, x1+2, "xx"); + testEnclosingName(x2+2, x2+2, "xx"); + testEnclosingName(x3, x3, "xx"); + testEnclosingName(x1-1, x1+2, null); + testEnclosingName(x2+2, x2+3, null); + testEnclosingName(x3-1, x3-1, null); + + testExpansion(x1, x1+2, null); + testExpansion(x2+2, x2+2, "xx"); + testExpansion(x3, x3, "xx"); + testExpansion(x2+2, x2+3, null); + testExpansion(x3-1, x3-1, null); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define xx 1 + // #if !defined(xx) + // #elif defined(xx) == 1 + // #endif + public void testMacroInDefinedExpression() { + int x1= fCode.indexOf("xx"); + int x2= fCode.indexOf("xx", x1+1); + int x3= fCode.indexOf("xx", x2+1); + + testContainedName(x1, x1+2, "xx"); + testContainedName(x2-1, x2+2, "xx"); + testContainedName(x3, x3+3, "xx"); + testContainedName(x1, x1+1, null); + testContainedName(x2+1, x2+2, null); + testContainedName(x3+1, x3+1, null); + + testName(x1, x1+2, "xx"); + testName(x2, x2+2, "xx"); + testName(x3, x3+2, "xx"); + testName(x1+1, x1+2, null); + testName(x2-1, x2+2, null); + testName(x3, x3+3, null); + testName(x3, x3+1, null); + + testEnclosingName(x1, x1+2, "xx"); + testEnclosingName(x2+2, x2+2, "xx"); + testEnclosingName(x3, x3, "xx"); + testEnclosingName(x1-1, x1+2, null); + testEnclosingName(x2+2, x2+3, null); + testEnclosingName(x3-1, x3-1, null); + + testExpansion(x1, x1+2, null); + testExpansion(x2+2, x2+2, null); + testExpansion(x3, x3, null); + testExpansion(x2+2, x2+3, null); + testExpansion(x3-1, x3-1, null); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define xx 1 + // #ifndef xx + // #endif + // #ifdef xx + // #endif + // #undef xx + public void testMacroInConditional() { + int x1= fCode.indexOf("xx"); + x1= fCode.indexOf("xx", x1+1); + int x2= fCode.indexOf("xx", x1+1); + int x3= fCode.indexOf("xx", x2+1); + + testContainedName(x1, x1+2, "xx"); + testContainedName(x2-1, x2+2, "xx"); + testContainedName(x3, x3+3, "xx"); + testContainedName(x1, x1+1, null); + testContainedName(x2+1, x2+2, null); + testContainedName(x3+1, x3+1, null); + + testName(x1, x1+2, "xx"); + testName(x2, x2+2, "xx"); + testName(x3, x3+2, "xx"); + testName(x1+1, x1+2, null); + testName(x2-1, x2+2, null); + testName(x3, x3+3, null); + testName(x3, x3+1, null); + + testEnclosingName(x1, x1+2, "xx"); + testEnclosingName(x2+2, x2+2, "xx"); + testEnclosingName(x3, x3, "xx"); + testEnclosingName(x1-1, x1+2, null); + testEnclosingName(x2+2, x2+3, null); + testEnclosingName(x3-1, x3-1, null); + + testExpansion(x1, x1+2, null); + testExpansion(x2+2, x2+2, null); + testExpansion(x3, x3, null); + testExpansion(x2+2, x2+3, null); + testExpansion(x3-1, x3-1, null); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define IMPLICIT 1 + // #define EXPLICIT IMPLICIT + // int a= EXPLICIT; + public void testUnreachableImplicitMacro() { + int x1= fCode.indexOf("EXPLICIT;"); + testContainedName(x1, fCode.length(), "EXPLICIT"); + testName(x1, x1+8, "EXPLICIT"); + testEnclosingName(x1, 0, "EXPLICIT"); + } + + // #define shift_offsets + // int shift= shift_offsets; + // + // #define NESTED 1 + // #define EXPLICIT(x) x + // int a= EXPLICIT(NESTED); + public void testReachableNestedMacro() { + int x1= fCode.indexOf("NESTED)"); + testContainedName(x1, fCode.length(), "NESTED"); + testName(x1, x1+6, "NESTED"); + testEnclosingName(x1, 0, "NESTED"); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 19eee7ece02..3915b19a736 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2007 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 @@ -40,6 +40,7 @@ public class DOMParserTestSuite extends TestCase { suite.addTestSuite( AST2UtilTests.class ); suite.addTestSuite( AST2UtilOldTests.class ); suite.addTestSuite( AST2SelectionParseTest.class ); + suite.addTest( ASTNodeSelectorTest.suite()); suite.addTestSuite( CodeReaderCacheTest.class ); suite.addTestSuite( AST2CPPSpecTest.class ); suite.addTestSuite( AST2CPPSpecFailingTest.class ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java index 4a43f8cec18..5800debc5fc 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java @@ -283,7 +283,7 @@ public class LocationMapTests extends BaseTestCase { private void checkMacroUndef(IASTPreprocessorStatement s, IBinding binding, String image, String name, String nameImage, String filename, int offset, int length, int line, int nameOffset, int nameLength) { IASTPreprocessorUndefStatement st= (IASTPreprocessorUndefStatement) s; - checkName(st.getMacroName(), binding, name, st, IASTPreprocessorUndefStatement.MACRO_NAME, ROLE_UNCLEAR, filename, nameOffset, nameLength, line, line, nameImage); + checkName(st.getMacroName(), binding, name, st, IASTPreprocessorStatement.MACRO_NAME, ROLE_UNCLEAR, filename, nameOffset, nameLength, line, line, nameImage); checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, image); } @@ -344,8 +344,8 @@ public class LocationMapTests extends BaseTestCase { public void testIf() { init(DIGITS); - fLocationMap.encounterPoundIf(0, 0, 0, 0, false); - fLocationMap.encounterPoundIf(0, 1, 3, 16, true); + fLocationMap.encounterPoundIf(0, 0, 0, 0, false, IASTName.EMPTY_NAME_ARRAY); + fLocationMap.encounterPoundIf(0, 1, 3, 16, true, IASTName.EMPTY_NAME_ARRAY); IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); assertEquals(2, prep.length); checkIf(prep[0], "", "", false, FN, 0, 0, 1); @@ -354,8 +354,8 @@ public class LocationMapTests extends BaseTestCase { public void testIfdef() { init(DIGITS); - fLocationMap.encounterPoundIfdef(0, 0, 0, 0, false); - fLocationMap.encounterPoundIfdef(0, 1, 3, 16, true); + fLocationMap.encounterPoundIfdef(0, 0, 0, 0, false, null); + fLocationMap.encounterPoundIfdef(0, 1, 3, 16, true, null); IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); assertEquals(2, prep.length); checkIfdef(prep[0], "", "", false, FN, 0, 0, 1); @@ -364,8 +364,8 @@ public class LocationMapTests extends BaseTestCase { public void testIfndef() { init(DIGITS); - fLocationMap.encounterPoundIfndef(0, 0, 0, 0, false); - fLocationMap.encounterPoundIfndef(0, 1, 3, 16, true); + fLocationMap.encounterPoundIfndef(0, 0, 0, 0, false, null); + fLocationMap.encounterPoundIfndef(0, 1, 3, 16, true, null); IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); assertEquals(2, prep.length); checkIfndef(prep[0], "", "", false, FN, 0, 0, 1); @@ -374,8 +374,8 @@ public class LocationMapTests extends BaseTestCase { public void testElif() { init(DIGITS); - fLocationMap.encounterPoundElif(0, 0, 0, 0, false); - fLocationMap.encounterPoundElif(0, 1, 3, 16, true); + fLocationMap.encounterPoundElif(0, 0, 0, 0, false, IASTName.EMPTY_NAME_ARRAY); + fLocationMap.encounterPoundElif(0, 1, 3, 16, true, IASTName.EMPTY_NAME_ARRAY); IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); assertEquals(2, prep.length); checkElif(prep[0], "", "", false, FN, 0, 0, 1); @@ -476,11 +476,11 @@ public class LocationMapTests extends BaseTestCase { refs= fLocationMap.getReferences(macro1); assertEquals(1, refs.length); - checkName(refs[0], macro1, "n1", refs[0].getParent(), IASTPreprocessorMacroExpansion.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15)); + checkName(refs[0], macro1, "n1", refs[0].getParent(), IASTPreprocessorMacroExpansion.NESTED_EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15)); refs= fLocationMap.getReferences(macro2); assertEquals(1, refs.length); - checkName(refs[0], macro2, "n2", refs[0].getParent(), IASTPreprocessorMacroExpansion.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15)); + checkName(refs[0], macro2, "n2", refs[0].getParent(), IASTPreprocessorMacroExpansion.NESTED_EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15)); } public void testContexts() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java index 636ee3cf6b4..0f304633edb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java @@ -11,8 +11,10 @@ package org.eclipse.cdt.core.dom.ast; /** - * Interface for searching nodes of a file in a translation unit. An instance of this interface can - * be obtained via {@link IASTTranslationUnit#getNodeSelector(String)}. + * Interface for searching nodes in a translation unit. An instance of this interface, responsible + * for one file contained in a translation-unit, can be obtained using + * {@link IASTTranslationUnit#getNodeSelector(String)}. + * * @since 5.0 */ public interface IASTNodeSelector { @@ -23,9 +25,9 @@ public interface IASTNodeSelector { IASTName findName(int offset, int length); /** - * Returns the smallest name surrounding the given range, or null if there is no such node. + * Returns the smallest name enclosing the given range, or null if there is no such node. */ - IASTName findSurroundingName(int offset, int length); + IASTName findEnclosingName(int offset, int length); /** * Returns the first name contained in the given range, or null if there is no such node. @@ -34,16 +36,31 @@ public interface IASTNodeSelector { /** * Returns the node for the exact given range, or null if there is no such node. + *

+ * For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred + * over c/c++-nodes and children are preferred over their parents. */ IASTNode findNode(int offset, int length); /** - * Returns the smallest node surrounding the given range, or null if there is no such node. + * Returns the smallest node enclosing the given range, or null if there is no such node. + *

+ * For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred + * over c/c++-nodes nodes and children are preferred over their parents. + * Prefers children over parents. */ - IASTNode findSurroundingNode(int offset, int length); + IASTNode findEnclosingNode(int offset, int length); /** * Returns the first node contained in the given range, or null if there is no such node. + *

+ * For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred + * over c/c++-nodes nodes and children are preferred over their parents. */ IASTNode findFirstContainedNode(int offset, int length); + + /** + * Returns a macro expansion enclosing the given range, or null. + */ + IASTPreprocessorMacroExpansion findEnclosingMacroExpansion(int offset, int length); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfdefStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfdefStatement.java index 43e2011baec..032aba080e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfdefStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfdefStatement.java @@ -1,35 +1,34 @@ /******************************************************************************* - * Copyright (c) 2004, 2007 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Emanuel Graf (IFS) + * IBM - Initial API and implementation + * Emanuel Graf (IFS) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; /** * This interface represent a preprocessor #ifdef statement. - * - * @author jcamelon */ -public interface IASTPreprocessorIfdefStatement extends - IASTPreprocessorStatement { +public interface IASTPreprocessorIfdefStatement extends IASTPreprocessorStatement { /** - * Was this #ifdef branch taken? - * - * @return + * Returns whether this branch was taken. */ public boolean taken(); /** - * The condition of the ifdef. - * - * @return the Condition + * The condition of the ifdef-statement. + * @return the condition */ public char[] getCondition(); + + /** + * Returns the macro reference, or null if the macro does not exist. + */ + IASTName getMacroReference(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfndefStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfndefStatement.java index 961cb517091..5cf7b687300 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfndefStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIfndefStatement.java @@ -1,34 +1,34 @@ /******************************************************************************* - * Copyright (c) 2004, 2007 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Emanuel Graf (IFS) + * IBM - Initial API and implementation + * Emanuel Graf (IFS) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; /** * This interface represent a preprocessor #ifndef statement. - * - * @author jcamelon */ -public interface IASTPreprocessorIfndefStatement extends - IASTPreprocessorStatement { +public interface IASTPreprocessorIfndefStatement extends IASTPreprocessorStatement { /** - * Was this branch taken? - * - * @return + * Returns whether this branch was taken. */ public boolean taken(); + /** - * The condition of the ifndef. - * - * @return the Condition + * Returns the condition of the ifndef-statement. */ public char[] getCondition(); + + /** + * Returns the macro reference, or null if the macro does not exist. + */ + IASTName getMacroReference(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java index 84028700725..1da1cd67724 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java @@ -18,6 +18,8 @@ public interface IASTPreprocessorMacroExpansion extends IASTNode { public static final IASTPreprocessorMacroExpansion[] EMPTY_ARRAY = {}; public static final ASTNodeProperty EXPANSION_NAME= new ASTNodeProperty("IASTPreprocessorMacroExpansion.EXPANSION_NAME - macro name"); //$NON-NLS-1$ + public static final ASTNodeProperty NESTED_EXPANSION_NAME= + new ASTNodeProperty("IASTPreprocessorMacroExpansion.NESTED_EXPANSION_NAME - nested macro name"); //$NON-NLS-1$ /** * Returns the macro definition used for the expansion. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorStatement.java index 504f4522111..ba6cc5190af 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorStatement.java @@ -1,20 +1,19 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; /** * This is the base interface for all preprocessor directives. - * - * @author jcamelon */ public interface IASTPreprocessorStatement extends IASTNode { - + public static final ASTNodeProperty MACRO_NAME = new ASTNodeProperty( "IASTPreprocessorStatement.MACRO_NAME - the name of a macro"); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorUndefStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorUndefStatement.java index d0537198390..482ac77cf34 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorUndefStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorUndefStatement.java @@ -1,24 +1,23 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; /** * This interface represents a preprocessor #undef statement. - * - * @author jcamelon */ -public interface IASTPreprocessorUndefStatement extends - IASTPreprocessorStatement { +public interface IASTPreprocessorUndefStatement extends IASTPreprocessorStatement { - public static final ASTNodeProperty MACRO_NAME = new ASTNodeProperty( "IASTPreprocessorUndefStatement.MACRO_NAME - the name of the macro being undefined"); //$NON-NLS-1$ + /** + * Returns the reference to the macro, or null. + */ public IASTName getMacroName(); - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java deleted file mode 100644 index 20acf3266c5..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 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.dom.parser; - -import org.eclipse.cdt.core.dom.ast.IASTName; - -/** - * For searching ast-nodes by offset and length, instances of this class can be used to - * determine whether a node matches or not. - * - * @since 5.0 - */ -public class ASTNodeMatchKind { - public enum Relation {FIRST_CONTAINED, EXACT, SURROUNDING} - - static final ASTNodeMatchKind MATCH_EXACT= new ASTNodeMatchKind(Relation.EXACT, false); - static final ASTNodeMatchKind MATCH_EXACT_NAME= new ASTNodeMatchKind(Relation.EXACT, true); - static final ASTNodeMatchKind MATCH_FIRST_CONTAINED= new ASTNodeMatchKind(Relation.FIRST_CONTAINED, false); - static final ASTNodeMatchKind MATCH_FIRST_NAME_CONTAINED= new ASTNodeMatchKind(Relation.FIRST_CONTAINED, true); - static final ASTNodeMatchKind MATCH_SURROUNDING= new ASTNodeMatchKind(Relation.SURROUNDING, false); - static final ASTNodeMatchKind MATCH_SURROUNDING_NAME= new ASTNodeMatchKind(Relation.SURROUNDING, true); - - private boolean fNamesOnly; - private Relation fRelation; - - private ASTNodeMatchKind(Relation relation, boolean namesOnly) { - fRelation= relation; - fNamesOnly= namesOnly; - } - - public Relation getRelationToSelection() { - return fRelation; - } - - public boolean matchNamesOnly() { - return fNamesOnly; - } - - /** - * Returns whether the node matches the selection. - */ - public boolean matches(ASTNode node, int selOffset, int selLength) { - return isAcceptableNode(node) && rangeMatches(node.getOffset(), node.getLength(), selOffset, selLength); - } - - public boolean isAcceptableNode(ASTNode astNode) { - return !fNamesOnly || astNode instanceof IASTName; - } - - /** - * Returns whether the node range matches the selection. - */ - public boolean rangeMatches(final int nodeOffset, final int nodeLength, int selOffset, - int selLength) { - switch(fRelation) { - case EXACT: - return selOffset == nodeOffset && selLength == nodeLength; - case FIRST_CONTAINED: - return selOffset <= nodeOffset && nodeOffset+nodeLength <= selOffset+selLength; - case SURROUNDING: - return nodeOffset <= selOffset && selOffset+selLength <= nodeOffset+nodeLength; - default: - assert false; - return false; - } - } - - /** - * Returns whether the node is a lower bound for matching the selection. A node is a lower - * bound when a node to the left of the given one cannot match the selection. - */ - public boolean isLowerBound(ASTNode node, int selOffset, int selLength) { - final int nodeOffset= node.getOffset(); - switch(fRelation) { - case SURROUNDING: - case EXACT: - return nodeOffset < selOffset+selLength; - case FIRST_CONTAINED: - return nodeOffset <= selOffset; - default: - assert false; - return false; - } - } - - /** - * Returns whether cand1 is a better match than cand2, prefers cand1 in case of doubt. - */ - public boolean isBetterMatch(ASTNode cand1, ASTNode cand2) { - if (cand1 == null) - return false; - if (cand2 == null) - return true; - - final int nodeOffset1= cand1.getOffset(); - final int nodeLength1= cand1.getLength(); - final int nodeOffset2= cand2.getOffset(); - final int nodeLength2= cand2.getLength(); - switch(fRelation) { - case EXACT: - return true; - case FIRST_CONTAINED: - return nodeOffset1 < nodeOffset2 || (nodeOffset1 == nodeOffset2 && nodeLength1 <= nodeLength2); - case SURROUNDING: - return nodeLength1 <= nodeLength2; - default: - assert false; - return false; - } - } -} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java index 75b1fbe130f..8dc40246ec0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java @@ -10,16 +10,15 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation; 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.IASTNodeSelector; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification.Relation; import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver; /** - * Class to support searching for nodes by offsets. + * Class to support searching for nodes by file offsets. * @since 5.0 */ public class ASTNodeSelector implements IASTNodeSelector { @@ -49,85 +48,99 @@ public class ASTNodeSelector implements IASTNodeSelector { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) */ - private IASTNode getNode(int offset, int length, ASTNodeMatchKind matchKind) { + private T findNode(int offsetInFile, int lengthInFile, Relation relation, Class requiredClass) { if (!fIsValid) { return null; } - - final int sequenceNumber= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offset); + int sequenceLength; + int altSequenceNumber= -1; + int sequenceNumber= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offsetInFile); if (sequenceNumber < 0) { return null; } - final int sequenceLength= length <= 0 ? 0 : - fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offset+length-1) + 1 - sequenceNumber; - - ASTNode preCand= searchPreprocessor(sequenceNumber, sequenceLength, matchKind); - if (preCand != null && matchKind.getRelationToSelection() != Relation.FIRST_CONTAINED) { - return preCand; - } - ASTNode astCand= searchAST(sequenceNumber, sequenceLength, matchKind); - return matchKind.isBetterMatch(preCand, astCand) ? preCand : astCand; - } - - private ASTNode searchPreprocessor(int sequenceNumber, int sequenceLength, ASTNodeMatchKind matchKind) { - return fLocationResolver.findPreprocessorNode(sequenceNumber, sequenceLength, matchKind); - } - - private ASTNode searchAST(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - FindNodeForOffsetAction nodeFinder= new FindNodeForOffsetAction(sequenceNumber, length, matchKind); - fTu.accept(nodeFinder); - ASTNode result= nodeFinder.getNode(); - // don't accept matches from the ast enclosed in a macro expansion (possible for contained matches, only) - if (result != null && - matchKind.getRelationToSelection() == Relation.FIRST_CONTAINED) { - IASTNodeLocation[] loc= result.getNodeLocations(); - if (loc.length > 0 && loc[0] instanceof IASTMacroExpansionLocation) { - return null; + if (lengthInFile > 0) { + sequenceLength= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offsetInFile+lengthInFile-1) + 1 - sequenceNumber; + } + else { + sequenceLength= 0; + if (offsetInFile > 0) { + altSequenceNumber= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offsetInFile-1); + if (altSequenceNumber+1 == sequenceNumber) { + altSequenceNumber= -1; + } + else { + // we are on a context boundary and we need to check the variant to the left and + // the one to the right + sequenceLength= 1; + } } } - return result; + final ASTNodeSpecification nodeSpec= new ASTNodeSpecification(relation, requiredClass, offsetInFile, lengthInFile); + nodeSpec.setRangeInSequence(sequenceNumber, sequenceLength); + getNode(nodeSpec); + if (altSequenceNumber != -1) { + nodeSpec.setRangeInSequence(altSequenceNumber, sequenceLength); + getNode(nodeSpec); + } + return nodeSpec.getBestNode(); + } + + private T getNode(ASTNodeSpecification nodeSpec) { + fLocationResolver.findPreprocessorNode(nodeSpec); + if (!nodeSpec.requiresClass(IASTPreprocessorMacroExpansion.class)) { + FindNodeForOffsetAction nodeFinder= new FindNodeForOffsetAction(nodeSpec); + fTu.accept(nodeFinder); + } + return nodeSpec.getBestNode(); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int) */ public IASTNode findFirstContainedNode(int offset, int length) { - return getNode(offset, length, ASTNodeMatchKind.MATCH_FIRST_CONTAINED); + return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) */ public IASTNode findNode(int offset, int length) { - return getNode(offset, length, ASTNodeMatchKind.MATCH_EXACT); + return findNode(offset, length, Relation.EXACT_MATCH, IASTNode.class); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int) */ - public IASTNode findSurroundingNode(int offset, int length) { - return getNode(offset, length, ASTNodeMatchKind.MATCH_SURROUNDING); + public IASTNode findEnclosingNode(int offset, int length) { + return findNode(offset, length, Relation.ENCLOSING, IASTNode.class); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int) */ public IASTName findFirstContainedName(int offset, int length) { - return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_FIRST_NAME_CONTAINED); + return findNode(offset, length, Relation.FIRST_CONTAINED, IASTName.class); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) */ public IASTName findName(int offset, int length) { - return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_EXACT_NAME); + return findNode(offset, length, Relation.EXACT_MATCH, IASTName.class); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int) */ - public IASTName findSurroundingName(int offset, int length) { - return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_SURROUNDING_NAME); + public IASTName findEnclosingName(int offset, int length) { + return findNode(offset, length, Relation.ENCLOSING, IASTName.class); } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#findSurrundingMacroExpansion(int, int) + */ + public IASTPreprocessorMacroExpansion findEnclosingMacroExpansion(int offset, int length) { + return findNode(offset, length, Relation.ENCLOSING, IASTPreprocessorMacroExpansion.class); + } + } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java new file mode 100644 index 00000000000..821ca3e595c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2008 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.dom.parser; + +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTImageLocation; +import org.eclipse.cdt.core.dom.ast.IASTNode; + +/** + * For searching ast-nodes by offset and length, instances of this class can be used to + * determine whether a node matches or not. + * + * @since 5.0 + */ +public class ASTNodeSpecification { + public enum Relation {FIRST_CONTAINED, EXACT_MATCH, ENCLOSING} + + private final Class fClass; + private final Relation fRelation; + private final int fFileOffset; + private final int fFileEndOffset; + private int fSeqNumber; + private int fSeqEndNumber; + private int fBestOffset; + private int fBestEndOffset; + private T fBestNode; + + public ASTNodeSpecification(Relation relation, Class clazz, int fileOffset, int fileLength) { + fRelation= relation; + fClass= clazz; + fFileOffset= fileOffset; + fFileEndOffset= fileOffset+fileLength; + } + + public void setRangeInSequence(int offsetInSeq, int lengthInSeq) { + fSeqNumber= offsetInSeq; + fSeqEndNumber= offsetInSeq+lengthInSeq; + } + + public Relation getRelationToSelection() { + return fRelation; + } + + public int getSequenceStart() { + return fSeqNumber; + } + + public int getSequenceEnd() { + return fSeqEndNumber; + } + + public T getBestNode() { + return fBestNode; + } + + public boolean requiresClass(Class clazz) { + return clazz.isAssignableFrom(fClass); + } + + @SuppressWarnings("unchecked") + public void visit(ASTNode astNode) { + if (isAcceptableNode(astNode) && isMatchingRange(astNode.getOffset(), astNode.getLength(), fSeqNumber, fSeqEndNumber)) { + IASTFileLocation loc= astNode.getFileLocation(); + if (loc != null) { + storeIfBest(loc, (T) astNode); + } + } + } + @SuppressWarnings("unchecked") + public void visit(ASTNode astNode, IASTImageLocation imageLocation) { + if (isAcceptableNode(astNode) && imageLocation != null) { + if (isMatchingRange(imageLocation.getNodeOffset(), imageLocation.getNodeLength(), fFileOffset, fFileEndOffset)) { + storeIfBest(imageLocation, (T) astNode); + } + } + } + + private boolean isMatchingRange(int offset, int length, int selOffset, int selEndOffset) { + final int endOffset= offset+length; + switch(fRelation) { + case EXACT_MATCH: + return selOffset == offset && selEndOffset == endOffset; + case FIRST_CONTAINED: + return selOffset <= offset && endOffset <= selEndOffset; + case ENCLOSING: + return offset <= selOffset && selEndOffset <= endOffset; + default: + assert false; + return false; + } + } + + public boolean isAcceptableNode(IASTNode astNode) { + return astNode != null && fClass.isAssignableFrom(astNode.getClass()); + } + + /** + * Returns whether the node can contain matches in its range. + */ + public boolean canContainMatches(ASTNode node) { + final int offset= node.getOffset(); + final int endOffset= offset+node.getLength(); + switch(fRelation) { + case EXACT_MATCH: + case ENCLOSING: + return offset <= fSeqNumber && fSeqEndNumber <= endOffset; + case FIRST_CONTAINED: + return offset <= fSeqEndNumber && fSeqNumber <= endOffset; + default: + assert false; + return false; + } + } + + private void storeIfBest(IASTFileLocation loc, T astNode) { + if (loc != null) { + final int offset = loc.getNodeOffset(); + final int length = loc.getNodeLength(); + if (isBetterMatch(offset, length, astNode)) { + fBestNode= astNode; + fBestOffset= offset; + fBestEndOffset= offset+length; + } + } + } + + /** + * Assuming that the given range matches, this method returns whether the match is better + * than the best match stored. + */ + private boolean isBetterMatch(int offset, int length, IASTNode cand) { + if (fBestNode == null) { + return true; + } + + final int endOffset= offset+length; + switch(fRelation) { + case EXACT_MATCH: + return !isParent(cand, fBestNode); + case FIRST_CONTAINED: + if (offset < fBestOffset) { + return true; + } + if (offset == fBestOffset) { + if (endOffset < fBestEndOffset) { + return true; + } + return endOffset == fBestEndOffset && !isParent(cand, fBestNode); + } + return false; + case ENCLOSING: + final int bestLength= fBestEndOffset-fBestOffset; + if (length < bestLength) { + return true; + } + return length == bestLength && !isParent(cand, fBestNode); + default: + assert false; + return false; + } + } + + private boolean isParent(IASTNode cand1, IASTNode cand2) { + while(cand2 != null) { + if (cand2 == cand1) { + return true; + } + cand2= cand2.getParent(); + } + return false; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java index 143d932905d..49eff99d944 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java @@ -38,16 +38,15 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +/** + * Visitor to search for nodes by file offsets. + * @since 5.0 + */ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisitor, ICPPASTVisitor { - private ASTNode fCandidate= null; - private final int fOffset; - private final int fLength; - private final ASTNodeMatchKind fMatchKind; + private final ASTNodeSpecification fNodeSpec; - public FindNodeForOffsetAction(int offset, int length, ASTNodeMatchKind matchKind) { - fMatchKind= matchKind; - fOffset = offset; - fLength = length; + public FindNodeForOffsetAction(ASTNodeSpecification nodeSpec) { + fNodeSpec= nodeSpec; shouldVisitNames = true; shouldVisitDeclarations= true; @@ -65,21 +64,16 @@ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisit shouldVisitBaseSpecifiers= shouldVisitNamespaces= shouldVisitTemplateParameters= - shouldVisitTranslationUnit= !matchKind.matchNamesOnly(); + shouldVisitTranslationUnit= !nodeSpec.requiresClass(IASTName.class); } public int processNode(IASTNode node) { if (node instanceof ASTNode) { final ASTNode astNode = (ASTNode) node; - if (astNode.getOffset() > fOffset+fLength || astNode.getOffset() + astNode.getLength() < fOffset) { + if (!fNodeSpec.canContainMatches(astNode)) { return PROCESS_SKIP; } - - if (fMatchKind.matches(astNode, fOffset, fLength)) { - if (fCandidate == null || !fMatchKind.isBetterMatch(fCandidate, astNode)) { - fCandidate= astNode; - } - } + fNodeSpec.visit(astNode); } return PROCESS_CONTINUE; } @@ -88,7 +82,7 @@ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisit public int visit(IASTDeclaration declaration) { // use declarations to determine if the search has gone past the // offset (i.e. don't know the order the visitor visits the nodes) - if (declaration instanceof ASTNode && ((ASTNode) declaration).getOffset() > fOffset + fLength) + if (declaration instanceof ASTNode && ((ASTNode) declaration).getOffset() > fNodeSpec.getSequenceEnd()) return PROCESS_ABORT; return processNode(declaration); @@ -204,8 +198,4 @@ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisit public int visit(IASTTranslationUnit tu) { return processNode(tu); } - - public ASTNode getNode() { - return fCandidate; - } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java index 8c97b1d4814..04456fcabc6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java @@ -18,7 +18,6 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation; 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.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; @@ -127,8 +126,8 @@ class ASTBuiltinName extends ASTPreprocessorDefinition { class ASTMacroReferenceName extends ASTPreprocessorName { private ImageLocationInfo fImageLocationInfo; - public ASTMacroReferenceName(IASTPreprocessorMacroExpansion parent, int offset, int endOffset, IMacroBinding macro, ImageLocationInfo imgLocationInfo) { - super(parent, IASTPreprocessorMacroExpansion.EXPANSION_NAME, offset, endOffset, macro.getNameCharArray(), macro); + public ASTMacroReferenceName(IASTNode parent, ASTNodeProperty property, int offset, int endOffset, IMacroBinding macro, ImageLocationInfo imgLocationInfo) { + super(parent, property, offset, endOffset, macro.getNameCharArray(), macro); fImageLocationInfo= imgLocationInfo; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index fa8f7cbdae1..5dc1d3d2e52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -34,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorObjectStyleMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -42,8 +43,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification; /** * Models various AST-constructs obtained from the preprocessor. @@ -72,36 +72,10 @@ abstract class ASTPreprocessorNode extends ASTNode { } /** - * Returns a matching node or null. + * Searches nodes by file location. */ - ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - if (matchKind.matches(this, sequenceNumber, length)) { - return this; - } - return null; - } - - /** - * Helper method for preprocessor nodes containing a name - */ - protected ASTNode findNode(int sequenceNumber, int length, ASTPreprocessorName name, ASTNodeMatchKind matchKind) { - ASTNode n1, n2; - if (matchKind.getRelationToSelection() == Relation.SURROUNDING) { - n1= name; - n2= this; - } - else { - n1= this; - n2= name; - } - - if (matchKind.matches(n1, sequenceNumber, length)) { - return n1; - } - if (matchKind.matches(n2, sequenceNumber, length)) { - return n2; - } - return null; + void findNode(ASTNodeSpecification nodeSpec) { + nodeSpec.visit(this); } } @@ -174,14 +148,35 @@ class ASTElse extends ASTPreprocessorNode implements IASTPreprocessorElseStateme } class ASTIfndef extends ASTDirectiveWithCondition implements IASTPreprocessorIfndefStatement { - public ASTIfndef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) { - super(parent, startNumber, condNumber, condEndNumber, active); + private ASTMacroReferenceName fMacroRef; + + public ASTIfndef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean taken, IMacroBinding macro) { + super(parent, startNumber, condNumber, condEndNumber, taken); + if (macro != null) { + fMacroRef= new ASTMacroReferenceName(this, IASTPreprocessorStatement.MACRO_NAME, condNumber, condEndNumber, macro, null); + } + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement#getMacroReference() + */ + public ASTPreprocessorName getMacroReference() { + return fMacroRef; } } class ASTIfdef extends ASTDirectiveWithCondition implements IASTPreprocessorIfdefStatement { - public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean active) { - super(parent, startNumber, condNumber, condEndNumber, active); + ASTMacroReferenceName fMacroRef; + public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean taken, IMacroBinding macro) { + super(parent, startNumber, condNumber, condEndNumber, taken); + if (macro != null) { + fMacroRef= new ASTMacroReferenceName(this, IASTPreprocessorStatement.MACRO_NAME, condNumber, condEndNumber, macro, null); + } + } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement#getMacroReference() + */ + public ASTPreprocessorName getMacroReference() { + return fMacroRef; } } @@ -250,8 +245,9 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces } @Override - ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - return findNode(sequenceNumber, length, fName, matchKind); + void findNode(ASTNodeSpecification nodeSpec) { + super.findNode(nodeSpec); + nodeSpec.visit(fName); } } @@ -308,8 +304,9 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor } @Override - ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - return findNode(sequenceNumber, length, fName, matchKind); + void findNode(ASTNodeSpecification nodeSpec) { + super.findNode(nodeSpec); + nodeSpec.visit(fName); } public void setExpansion(String exp) {assert false;} @@ -410,17 +407,12 @@ class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefState private final ASTPreprocessorName fName; public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, IBinding binding) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, nameEndNumber); - fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding); + fName= new ASTPreprocessorName(this, IASTPreprocessorStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding); } public ASTPreprocessorName getMacroName() { return fName; } - - @Override - ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - return findNode(sequenceNumber, length, fName, matchKind); - } } class ASTInclusionNode implements IASTInclusionNode { @@ -546,9 +538,13 @@ class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorM /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion#getNestedExpansions() */ - public IASTName[] getNestedMacroReferences() { + public ASTPreprocessorName[] getNestedMacroReferences() { return fContext.getNestedMacroReferences(); } + + public LocationCtxMacroExpansion getContext() { + return fContext; + } } @SuppressWarnings("deprecation") diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 379a6e6e0ed..68dcaa76f49 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -883,7 +883,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); int endOffset= lexer.currentToken().getEndOffset(); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { - fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false); + fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); skipOverConditionalCode(lexer, false); } else { @@ -1132,17 +1132,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); final int endOffset= lexer.currentToken().getEndOffset(); final char[] namechars= name.getCharImage(); - boolean isActive= (fMacroDictionary.get(namechars) != null) == positive; + PreprocessorMacro macro= fMacroDictionary.get(namechars); + boolean isActive= (macro != null) == positive; fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); if (positive) { - fLocationMap.encounterPoundIfdef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive); + fLocationMap.encounterPoundIfdef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); } else { - fLocationMap.encounterPoundIfndef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive); + fLocationMap.encounterPoundIfndef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); } - if (!isActive) { + if ((macro == null) == positive) { skipOverConditionalCode(lexer, true); } } @@ -1154,19 +1155,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final int condEndOffset= getTokensWithinPPDirective(lexer, true, condition); final int endOffset= lexer.currentToken().getEndOffset(); + fExpressionEvaluator.clearMacrosInDefinedExpression(); if (condition.first() == null) { handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); } else { try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary); + isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); } catch (EvalException e) { handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset); } } fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive); + fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); if (!isActive) { skipOverConditionalCode(lexer, true); @@ -1247,21 +1249,21 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { int endOffset= lexer.currentToken().getEndOffset(); nesting++; fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfdef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false); + fLocationMap.encounterPoundIfdef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); break; case IPreprocessorDirective.ppIfndef: lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); endOffset= lexer.currentToken().getEndOffset(); nesting++; fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfndef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false); + fLocationMap.encounterPoundIfndef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); break; case IPreprocessorDirective.ppIf: int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); endOffset= lexer.currentToken().getEndOffset(); nesting++; fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(pound.getOffset(), ident.getOffset(), condEndOffset, endOffset, false); + fLocationMap.encounterPoundIf(pound.getOffset(), ident.getOffset(), condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); break; case IPreprocessorDirective.ppElse: lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); @@ -1279,13 +1281,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { case IPreprocessorDirective.ppElif: if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { boolean isActive= false; + fExpressionEvaluator.clearMacrosInDefinedExpression(); int condOffset= lexer.nextToken().getOffset(); if (nesting == 0 && takeElseBranch) { TokenList condition= new TokenList(); condEndOffset= getTokensWithinPPDirective(lexer, true, condition); if (condition.first() != null) { try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary); + isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); } catch (EvalException e) { handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, condEndOffset); } @@ -1296,7 +1299,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } endOffset= lexer.currentToken().getEndOffset(); fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF); - fLocationMap.encounterPoundElif(pound.getOffset(), condOffset, condEndOffset, endOffset, isActive); + fLocationMap.encounterPoundElif(pound.getOffset(), condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); if (isActive) { return; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java index 0da348357f3..2bd913ee43b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java @@ -13,6 +13,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.parser.scanner; +import java.util.ArrayList; + +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.util.CharArrayMap; @@ -41,13 +44,22 @@ class ExpressionEvaluator { private Token fTokens; private CharArrayMap fDictionary; + private ArrayList fMacrosInDefinedExpressions= new ArrayList(); + private LocationMap fLocationMap; - public boolean evaluate(TokenList condition, CharArrayMap macroDictionary) throws EvalException { + public boolean evaluate(TokenList condition, CharArrayMap macroDictionary, LocationMap map) throws EvalException { fTokens= condition.first(); fDictionary= macroDictionary; + fLocationMap= map; + fMacrosInDefinedExpressions.clear(); return expression() != 0; } - + + public IASTName[] clearMacrosInDefinedExpression() { + IASTName[] result= fMacrosInDefinedExpressions.toArray(new IASTName[fMacrosInDefinedExpressions.size()]); + fMacrosInDefinedExpressions.clear(); + return result; + } private long expression() throws EvalException { return conditionalExpression(); @@ -254,7 +266,11 @@ class ExpressionEvaluator { if (LA() != IToken.tIDENTIFIER) { throw new EvalException(IProblem.SCANNER_ILLEGAL_IDENTIFIER, null); } - int result= fDictionary.containsKey(fTokens.getCharImage()) ? 1 : 0; + PreprocessorMacro macro= fDictionary.get(fTokens.getCharImage()); + if (macro != null) { + fMacrosInDefinedExpressions.add(fLocationMap.encounterDefinedExpression(macro, fTokens.getOffset(), fTokens.getEndOffset())); + } + int result= macro != null ? 1 : 0; consume(); if (parenthesis) { if (LA() != IToken.tRPAREN) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java index 189b092f6aa..06114cfc9c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java @@ -32,22 +32,21 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification; +/** + * Visitor to select nodes by image-location. + * @since 5.0 + */ public class FindNodeByImageLocation extends CPPASTVisitor implements ICASTVisitor, ICPPASTVisitor { - private ASTNode fCandidate= null; private final int fOffset; private final int fLength; - private final ASTNodeMatchKind fMatchKind; - private int fImageOffset; - private int fImageLength; + private final ASTNodeSpecification fNodeSpec; - public FindNodeByImageLocation(int offset, int length, int imgOffset, int imgLength, ASTNodeMatchKind matchKind) { - fMatchKind= matchKind; + public FindNodeByImageLocation(int offset, int length, ASTNodeSpecification nodeSpec) { + fNodeSpec= nodeSpec; fOffset = offset; fLength = length; - fImageOffset= imgOffset; - fImageLength= imgLength; shouldVisitNames = true; shouldVisitDeclarations= true; @@ -65,7 +64,7 @@ public class FindNodeByImageLocation extends CPPASTVisitor implements ICASTVisit shouldVisitBaseSpecifiers= shouldVisitNamespaces= shouldVisitTemplateParameters= - shouldVisitTranslationUnit= !matchKind.matchNamesOnly(); + shouldVisitTranslationUnit= !nodeSpec.requiresClass(IASTName.class); } public int processNode(IASTNode node) { @@ -75,14 +74,10 @@ public class FindNodeByImageLocation extends CPPASTVisitor implements ICASTVisit return PROCESS_SKIP; } - if (fMatchKind.isAcceptableNode(astNode)) { + if (fNodeSpec.isAcceptableNode(astNode)) { IASTImageLocation imageLocation= astNode.getImageLocation(); if (imageLocation != null && imageLocation.getLocationKind() == IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION) { - if (fMatchKind.rangeMatches(imageLocation.getNodeOffset(), imageLocation.getNodeLength(), fImageOffset, fImageLength)) { - if (fCandidate == null || !fMatchKind.isBetterMatch(fCandidate, astNode)) { - fCandidate= astNode; - } - } + fNodeSpec.visit(astNode, imageLocation); } } } @@ -184,8 +179,4 @@ public class FindNodeByImageLocation extends CPPASTVisitor implements ICASTVisit public int visit(IASTTranslationUnit tu) { return processNode(tu); } - - public ASTNode getNode() { - return fCandidate; - } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java index 25e1bcebd21..4981f12177e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java @@ -24,8 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; -import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification; /** @@ -136,16 +135,13 @@ public interface ILocationResolver { char[] getUnpreprocessedSignature(IASTFileLocation loc); /** - * Returns a preprocessor node surrounding the given range, or null. The result is either a - * preprocessing directive ({@link IASTPreprocessorStatement}) or a name contained therein {@link IASTName} or - * a macro expansion ({@link IASTName}). + * Searches for a preprocessor node matching the given specification. Candidates are passed to + * nodeSpec, which selects and stores the best result. * - * @param sequenceNumber the sequence number of the start of the interesting region. - * @param length the sequence length of the interesting region. - * @param matchOption the kind of the desired match. + * @param nodeSpec specification of node to search for. */ - ASTNode findPreprocessorNode(int sequenceNumber, int length, ASTNodeMatchKind matchOption); - + void findPreprocessorNode(ASTNodeSpecification nodeSpec); + /** * Returns whether the specified sequence number points into the root file of the * translation unit, or not. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java index 97ec22d0369..4eef1b81495 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java @@ -94,7 +94,7 @@ abstract class LocationCtx implements ILocationCtx { /** * Returns the macro-expansion surrounding or augmenting the given range, or null. */ - public LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) { + public LocationCtxMacroExpansion findEnclosingMacroExpansion(int sequenceNumber, int length) { return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java index d67bb91168b..41b376766d9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java @@ -101,11 +101,11 @@ class LocationCtxContainer extends LocationCtx { } @Override - public final LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) { + public final LocationCtxMacroExpansion findEnclosingMacroExpansion(int sequenceNumber, int length) { int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, true); if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { - return child.findSurroundingMacroExpansion(sequenceNumber, length); + return child.findEnclosingMacroExpansion(sequenceNumber, length); } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java index 753203b6b44..5346a3f9b4d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java @@ -16,9 +16,6 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.dom.ast.IMacroBinding; -import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; /** * A location context representing macro expansions. @@ -74,7 +71,7 @@ class LocationCtxMacroExpansion extends LocationCtx { } @Override - public LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) { + public LocationCtxMacroExpansion findEnclosingMacroExpansion(int sequenceNumber, int length) { return this; } @@ -109,26 +106,6 @@ class LocationCtxMacroExpansion extends LocationCtx { return null; } - public ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - ASTNode n1, n2; - if (matchKind.getRelationToSelection() == Relation.SURROUNDING) { - n1= fExpansionName; - n2= (ASTNode) fExpansionName.getParent(); - } - else { - n1= (ASTNode) fExpansionName.getParent(); - n2= fExpansionName; - } - - if (matchKind.matches(n1, sequenceNumber, length)) { - return n1; - } - if (matchKind.matches(n2, sequenceNumber, length)) { - return n2; - } - return null; - } - public ASTPreprocessorName[] getNestedMacroReferences() { return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent()); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java index 9b300aa3e09..0208d7cbce7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTImageLocation; 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; @@ -31,10 +32,8 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.parser.util.CharArrayUtils; -import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification; import org.eclipse.cdt.internal.core.dom.parser.ASTProblem; -import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; /** * Converts the offsets relative to various contexts to the global sequence number. Also creates and stores @@ -138,9 +137,20 @@ public class LocationMap implements ILocationResolver { * @param imageLocationInfo the image-location for the name of the macro. */ public IASTName encounterImplicitMacroExpansion(IMacroBinding macro, ImageLocationInfo imageLocationInfo) { - return new ASTMacroReferenceName(null, 0, 0, macro, imageLocationInfo); + return new ASTMacroReferenceName(null, IASTPreprocessorMacroExpansion.NESTED_EXPANSION_NAME, 0, 0, macro, imageLocationInfo); } + /** + * Creates a name representing a macro in a defined-expression. The returned name can be fed into + * {@link #encounterPoundIf(int, int, int, int, boolean, IASTName[])}. + */ + public IASTName encounterDefinedExpression(IMacroBinding macro, int startOffset, int endOffset) { + int startNumber= getSequenceNumberForOffset(startOffset); + int endNumber= getSequenceNumberForOffset(endOffset); + return new ASTMacroReferenceName(null, IASTPreprocessorStatement.MACRO_NAME, startNumber, endNumber, macro, null); + } + + /** * Creates a new context for the result of a (recursive) macro-expansion. * @param nameOffset offset within the current context where the name for the macro-expansion starts. @@ -160,14 +170,14 @@ public class LocationMap implements ILocationResolver { final int length= endNumber-nameNumber; ASTMacroExpansion expansion= new ASTMacroExpansion(fTranslationUnit, nameNumber, endNumber); - ASTMacroReferenceName explicitRef= new ASTMacroReferenceName(expansion, nameNumber, nameEndNumber, macro, null); + ASTMacroReferenceName explicitRef= new ASTMacroReferenceName(expansion, IASTPreprocessorMacroExpansion.EXPANSION_NAME, nameNumber, nameEndNumber, macro, null); + addMacroReference(explicitRef); for (int i = 0; i < implicitMacroReferences.length; i++) { ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i]; name.setParent(expansion); name.setOffsetAndLength(nameNumber, length); addMacroReference(name); } - addMacroReference(explicitRef); LocationCtxMacroExpansion expansionCtx= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, explicitRef); expansion.setContext(expansionCtx); @@ -177,7 +187,9 @@ public class LocationMap implements ILocationResolver { } private void addMacroReference(ASTPreprocessorName name) { - fMacroReferences.add(name); + if (name != null) { + fMacroReferences.add(name); + } } /** @@ -233,12 +245,22 @@ public class LocationMap implements ILocationResolver { fDirectives.add(new ASTElse(fTranslationUnit, startOffset, endOffset, isActive)); } - public void encounterPoundElif(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) { + public void encounterPoundElif(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive, + IASTName[] macrosInDefinedExpression) { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTElif(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); + final ASTElif elif = new ASTElif(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive); + fDirectives.add(elif); + + for (int i = 0; i < macrosInDefinedExpression.length; i++) { + ASTMacroReferenceName name = (ASTMacroReferenceName) macrosInDefinedExpression[i]; + name.setParent(elif); + name.setPropertyInParent(IASTPreprocessorStatement.MACRO_NAME); + addMacroReference(name); + } + } public void encounterPoundEndIf(int startOffset, int endOffset) { @@ -263,30 +285,42 @@ public class LocationMap implements ILocationResolver { fDirectives.add(new ASTPragma(fTranslationUnit, startOffset, condOffset, condEndOffset)); } - public void encounterPoundIfdef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) { + public void encounterPoundIfdef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean taken, IMacroBinding macro) { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); + final ASTIfdef ifdef = new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, taken, macro); + fDirectives.add(ifdef); + addMacroReference(ifdef.getMacroReference()); } - public void encounterPoundIfndef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) { + public void encounterPoundIfndef(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean taken, IMacroBinding macro) { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); + final ASTIfndef ifndef = new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, taken, macro); + fDirectives.add(ifndef); + addMacroReference(ifndef.getMacroReference()); } - public void encounterPoundIf(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive) { + public void encounterPoundIf(int startOffset, int condOffset, int condEndOffset, int endOffset, boolean isActive, + IASTName[] macrosInDefinedExpression) { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); + final ASTIf astif = new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive); + fDirectives.add(astif); + for (int i = 0; i < macrosInDefinedExpression.length; i++) { + ASTMacroReferenceName name = (ASTMacroReferenceName) macrosInDefinedExpression[i]; + name.setParent(astif); + name.setPropertyInParent(IASTPreprocessorStatement.MACRO_NAME); + addMacroReference(name); + } } - + public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, IMacroBinding macrodef) { startOffset= getSequenceNumberForOffset(startOffset); nameOffset= getSequenceNumberForOffset(nameOffset); @@ -434,59 +468,93 @@ public class LocationMap implements ILocationResolver { return null; } - public ASTNode findPreprocessorNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { - int lower=0; - int upper= fDirectives.size()-1; - while(lower <= upper) { - int middle= (lower+upper)/2; - ASTPreprocessorNode candidate= fDirectives.get(middle); - ASTNode result= candidate.findNode(sequenceNumber, length, matchKind); - if (result != null) { - if (matchKind.getRelationToSelection() == Relation.FIRST_CONTAINED) { - if (middle>lower) { - upper= middle; // if (upper-lower == 1) then middle==lower - continue; - } - } - return result; - } - if (matchKind.isLowerBound(candidate, sequenceNumber, length)) { - lower= middle+1; - } - else { - upper= middle-1; + public void findPreprocessorNode(ASTNodeSpecification nodeSpec) { + final int sequenceStart= nodeSpec.getSequenceStart(); + final int sequenceEnd= nodeSpec.getSequenceEnd(); + + // check directives + int from= findLastNodeBefore(fDirectives, sequenceStart); + for (int i= from+1; i < fDirectives.size(); i++) { + ASTPreprocessorNode directive= fDirectives.get(i); + if (directive.getOffset() > sequenceEnd) { + break; } + directive.findNode(nodeSpec); } - // search for a macro-expansion - LocationCtxMacroExpansion ctx= fRootContext.findSurroundingMacroExpansion(sequenceNumber, length); - if (ctx != null) { - ASTNode candidate= ctx.findNode(sequenceNumber, length, matchKind); - int imageOffset= ctx.fEndOffsetInParent + sequenceNumber - ctx.fSequenceNumber; - if (fTranslationUnit != null) { - FindNodeByImageLocation visitor= new FindNodeByImageLocation(ctx.fSequenceNumber, ctx.getSequenceLength(), imageOffset, length, matchKind); - fTranslationUnit.accept(visitor); - ASTNode candidate2= visitor.getNode(); - if (matchKind.isBetterMatch(candidate2, candidate)) { - candidate= candidate2; - } + + // check macro references and expansions + from= findLastMacroReferenceBefore(fMacroReferences, sequenceStart); + for (int i= from+1; i < fMacroReferences.size(); i++) { + ASTPreprocessorNode macroRef= fMacroReferences.get(i); + if (macroRef.getOffset() > sequenceEnd) { + break; } - ASTPreprocessorName[] nested= ctx.getNestedMacroReferences(); - for (ASTPreprocessorName name : nested) { - IASTImageLocation imageLoc= name.getImageLocation(); - if (imageLoc != null && imageLoc.getLocationKind() == IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION) { - if (matchKind.rangeMatches(imageLoc.getNodeOffset(), imageLoc.getNodeLength(), imageOffset, length)) { - if (matchKind.isBetterMatch(name, candidate)) { - candidate= name; + if (macroRef.getPropertyInParent() == IASTPreprocessorMacroExpansion.NESTED_EXPANSION_NAME) { + continue; + } + nodeSpec.visit(macroRef); + IASTNode parent= macroRef.getParent(); + if (parent instanceof ASTMacroExpansion) { + ASTMacroExpansion expansion= (ASTMacroExpansion) parent; + assert expansion.getMacroReference() == macroRef; + + if (nodeSpec.canContainMatches(expansion)) { + nodeSpec.visit(expansion); + if (!nodeSpec.requiresClass(IASTPreprocessorMacroExpansion.class)) { + LocationCtxMacroExpansion ctx= expansion.getContext(); + if (fTranslationUnit != null) { + FindNodeByImageLocation visitor= new FindNodeByImageLocation(ctx.fSequenceNumber, ctx.getSequenceLength(), nodeSpec); + fTranslationUnit.accept(visitor); + } + ASTPreprocessorName[] nestedMacros= expansion.getNestedMacroReferences(); + for (ASTPreprocessorName nested : nestedMacros) { + IASTImageLocation imgLoc= nested.getImageLocation(); + if (imgLoc != null && imgLoc.getLocationKind() == IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION) { + nodeSpec.visit(nested, imgLoc); + } } } } } - return candidate; } - - return null; } + private int findLastNodeBefore(ArrayList nodes, int sequenceStart) { + int lower=-1; + int upper= nodes.size()-1; + while(lower < upper) { + int middle= (lower+upper+1)/2; + ASTPreprocessorNode candidate= nodes.get(middle); + if (candidate.getOffset() + candidate.getLength() >= sequenceStart) { + upper= middle-1; + } + else { + lower= middle; + } + } + return lower; + } + + private int findLastMacroReferenceBefore(ArrayList nodes, int sequenceStart) { + int lower=-1; + int upper= nodes.size()-1; + while(lower < upper) { + int middle= (lower+upper+1)/2; + ASTPreprocessorNode candidate= nodes.get(middle); + IASTNode parent= candidate.getParent(); + if (parent instanceof ASTMacroExpansion) { + candidate= (ASTMacroExpansion) parent; + } + if (candidate.getOffset() + candidate.getLength() >= sequenceStart) { + upper= middle-1; + } + else { + lower= middle; + } + } + return lower; + } + public int getSequenceNumberForFileOffset(String filePath, int fileOffset) { LocationCtx ctx= fRootContext; if (filePath != null) { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java index f0542bf22f9..873e8d076b9 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java @@ -1073,4 +1073,29 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde input = part.getEditorInput(); assertEquals("s.c", ((FileEditorInput)input).getFile().getName()); } + + // #define ADD_TEXT(txt1,txt2) txt1" "txt2 + // #define ADD(a,b) (a + b) + // void main(void) { + // #if defined(ADD_TEXT) && defined(ADD) + // #endif + // } + public void testNavigationInDefinedExpression_215906() throws Exception { + StringBuffer[] buffers= getContents(1); + String code= buffers[0].toString(); + IFile file = importFile("s.cpp", code); + TestSourceReader.waitUntilFileIsIndexed(index, file, MAX_WAIT_TIME); + IASTNode decl; + int offset1, offset2; + + offset1 = code.indexOf("ADD_TEXT"); + offset2 = code.indexOf("ADD_TEXT", offset1+1); + decl= testF3(file, offset2); + assertNode("ADD_TEXT", offset1, decl); + + offset1 = code.indexOf("ADD", offset1+1); + offset2 = code.indexOf("ADD", offset2+1); + decl= testF3(file, offset2); + assertNode("ADD", offset1, decl); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index 2ec01ca5487..c35cf075187 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -299,6 +299,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles, store); } + @Override public IContentAssistant getContentAssistant() { return fContentAssistant; } @@ -306,6 +307,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see ITextOperationTarget#doOperation(int) */ + @Override public void doOperation(int operation) { if (getTextWidget() == null) @@ -332,6 +334,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper) */ + @Override public boolean requestWidgetToken(IWidgetTokenKeeper requester) { if (PlatformUI.getWorkbench().getHelpSystem().isContextHelpDisplayed()) return false; @@ -342,6 +345,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see IWidgetTokenOwnerExtension#requestWidgetToken(IWidgetTokenKeeper, int) * @since 3.0 */ + @Override public boolean requestWidgetToken(IWidgetTokenKeeper requester, int priority) { if (PlatformUI.getWorkbench().getHelpSystem().isContextHelpDisplayed()) return false; @@ -352,6 +356,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.jface.text.source.SourceViewer#createFormattingContext() * @since 3.0 */ + @Override public IFormattingContext createFormattingContext() { IFormattingContext context= new FormattingContext(); @@ -796,6 +801,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.jface.action.IAction#run() */ + @Override public void run() { // Check whether sub word navigation is enabled. final IPreferenceStore store = getPreferenceStore(); @@ -861,6 +867,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.NextSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(final int position) { getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); } @@ -883,6 +890,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.NextSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(final int position) { if (!validateEditorInputState()) return; @@ -908,6 +916,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.NextSubWordAction#findNextPosition(int) */ + @Override protected int findNextPosition(int position) { return fIterator.following(position); } @@ -937,6 +946,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.NextSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(final int position) { final ISourceViewer viewer = getSourceViewer(); @@ -976,6 +986,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.jface.action.IAction#run() */ + @Override public void run() { // Check whether sub word navigation is enabled. final IPreferenceStore store = getPreferenceStore(); @@ -1041,6 +1052,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.PreviousSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(final int position) { getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); } @@ -1063,6 +1075,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.PreviousSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(int position) { if (!validateEditorInputState()) return; @@ -1087,6 +1100,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.PreviousSubWordAction#findPreviousPosition(int) */ + @Override protected int findPreviousPosition(int position) { return fIterator.preceding(position); } @@ -1116,6 +1130,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.cdt.internal.ui.editor.CEditor.PreviousSubWordAction#setCaretPosition(int) */ + @Override protected void setCaretPosition(final int position) { final ISourceViewer viewer = getSourceViewer(); @@ -1253,12 +1268,14 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor() */ + @Override protected void initializeEditor() { } /** * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetInput(org.eclipse.ui.IEditorInput) */ + @Override protected void doSetInput(IEditorInput input) throws CoreException { ISourceViewer sourceViewer= getSourceViewer(); if (!(sourceViewer instanceof ISourceViewerExtension2)) { @@ -1313,6 +1330,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore) * @since 5.0 */ + @Override protected void setPreferenceStore(IPreferenceStore store) { super.setPreferenceStore(store); SourceViewerConfiguration sourceViewerConfiguration= getSourceViewerConfiguration(); @@ -1349,7 +1367,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed() */ - public boolean isSaveAsAllowed() { + @Override + public boolean isSaveAsAllowed() { return true; } /** @@ -1368,6 +1387,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ + @Override public Object getAdapter(Class required) { if (IContentOutlinePage.class.equals(required)) { return getOutlinePage(); @@ -1421,6 +1441,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * * @param event the property change event */ + @Override protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { String property = event.getProperty(); @@ -1547,6 +1568,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#initializeViewerColors(org.eclipse.jface.text.source.ISourceViewer) */ + @Override protected void initializeViewerColors(ISourceViewer viewer) { // is handled by CSourceViewer } @@ -1821,6 +1843,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.ui.texteditor.AbstractTextEditor#installTabsToSpacesConverter() * @since 4.0 */ + @Override protected void installTabsToSpacesConverter() { ISourceViewer sourceViewer= getSourceViewer(); SourceViewerConfiguration config= getSourceViewerConfiguration(); @@ -1856,6 +1879,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isTabsToSpacesConversionEnabled() * @since 4.0 */ + @Override protected boolean isTabsToSpacesConversionEnabled() { ICElement element= getInputCElement(); ICProject project= element == null ? null : element.getCProject(); @@ -1870,7 +1894,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.IWorkbenchPart#dispose() */ - public void dispose() { + @Override + public void dispose() { ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer instanceof ITextViewerExtension) @@ -1943,6 +1968,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.texteditor.AbstractTextEditor#canHandleMove(org.eclipse.ui.IEditorInput, org.eclipse.ui.IEditorInput) */ + @Override protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) { String oldLanguage = ""; //$NON-NLS-1$ if (originalElement instanceof IFileEditorInput) { @@ -1977,6 +2003,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions() */ + @Override protected void createActions() { super.createActions(); @@ -2088,6 +2115,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /** * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager) */ + @Override public void editorContextMenuAboutToShow(IMenuManager menu) { // marker for contributions to the top menu.add(new GroupMarker(ICommonMenuConstants.GROUP_TOP)); @@ -2135,6 +2163,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#rulerContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager) */ + @Override protected void rulerContextMenuAboutToShow(IMenuManager menu) { super.rulerContextMenuAboutToShow(menu); IMenuManager foldingMenu= new MenuManager(CEditorMessages.getString("CEditor.menu.folding"), "projection"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -2174,6 +2203,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @see org.eclipse.ui.part.WorkbenchPart#getOrientation() * @since 4.0 */ + @Override public int getOrientation() { // C/C++ editors are always left to right by default return SWT.LEFT_TO_RIGHT; @@ -2182,6 +2212,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite) */ + @Override public void createPartControl(Composite parent) { super.createPartControl(parent); @@ -2213,6 +2244,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#installTextDragAndDrop(org.eclipse.jface.text.source.ISourceViewer) */ + @Override protected void installTextDragAndDrop(ISourceViewer viewer) { if (fTextViewerDragAdapter != null) { // already installed, enable it @@ -2239,6 +2271,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#uninstallTextDragAndDrop(org.eclipse.jface.text.source.ISourceViewer) */ + @Override protected void uninstallTextDragAndDrop(ISourceViewer viewer) { if (fTextViewerDragAdapter != null) { // uninstall not possible, disable instead @@ -2249,6 +2282,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#getSourceViewerDecorationSupport(org.eclipse.jface.text.source.ISourceViewer) */ + @Override protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) { if (fSourceViewerDecorationSupport == null) { fSourceViewerDecorationSupport= new CSourceViewerDecorationSupport(this, viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors()); @@ -2260,6 +2294,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#configureSourceViewerDecorationSupport(org.eclipse.ui.texteditor.SourceViewerDecorationSupport) */ + @Override protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) { super.configureSourceViewerDecorationSupport(support); //Enhance the stock source viewer decorator with a bracket matcher @@ -2387,6 +2422,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * Get the dektop's StatusLineManager */ + @Override protected IStatusLineManager getStatusLineManager() { IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor(); if (contributor instanceof EditorActionBarContributor) { @@ -2412,6 +2448,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions() */ + @Override protected void createNavigationActions() { super.createNavigationActions(); @@ -2457,6 +2494,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int) */ + @Override protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { IPreferenceStore store= getPreferenceStore(); ISourceViewer sourceViewer = @@ -2555,6 +2593,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.editors.text.TextEditor#initializeKeyBindingScopes() */ + @Override protected void initializeKeyBindingScopes() { setKeyBindingScopes(new String [] { "org.eclipse.cdt.ui.cEditorScope" } ); //$NON-NLS-1$ } @@ -2562,6 +2601,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent) */ + @Override protected boolean affectsTextPresentation(PropertyChangeEvent event) { SourceViewerConfiguration configuration = getSourceViewerConfiguration(); if (configuration instanceof CSourceViewerConfiguration) { @@ -2582,6 +2622,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert() */ + @Override protected void performRevert() { ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer(); projectionViewer.setRedraw(false); @@ -2612,7 +2653,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * * @param msg message to be set */ - protected void setStatusLineErrorMessage(String msg) { + @Override + protected void setStatusLineErrorMessage(String msg) { IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); if (statusLine != null) statusLine.setMessage(true, msg, null); @@ -2624,6 +2666,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC * @param msg message to be set * @since 3.0 */ + @Override protected void setStatusLineMessage(String msg) { IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); if (statusLine != null) @@ -2719,6 +2762,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#collectContextMenuPreferencePages() */ + @Override protected String[] collectContextMenuPreferencePages() { // Add C/C++ Editor relevant pages String[] parentPrefPageIds = super.collectContextMenuPreferencePages(); @@ -2848,6 +2892,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#updateStateDependentActions() */ + @Override protected void updateStateDependentActions() { super.updateStateDependentActions(); fGenerateActionGroup.editorStateChanged(); @@ -2905,6 +2950,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC /* * @see Job#run(org.eclipse.core.runtime.IProgressMonitor) */ + @Override public IStatus run(IProgressMonitor progressMonitor) { if (isCanceled(progressMonitor)) return Status.CANCEL_STATUS; @@ -3078,7 +3124,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IC OccurrenceLocation[] locations= null; IASTNodeSelector selector= astRoot.getNodeSelector(astRoot.getFilePath()); - IASTName name= selector.findSurroundingName(wordRegion.getOffset(), wordRegion.getLength()); + IASTName name= selector.findEnclosingName(wordRegion.getOffset(), wordRegion.getLength()); if (name != null) { IBinding binding= name.resolveBinding(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java index c9ae76a3599..7826f90de56 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java @@ -10,7 +10,6 @@ * IBM Corporation * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.ui.editor; import org.eclipse.core.runtime.CoreException; @@ -83,7 +82,7 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector { final int offset= region.getOffset(); final int length= Math.max(1, region.getLength()); final IASTNodeSelector nodeSelector= ast.getNodeSelector(null); - IASTName selectedName= nodeSelector.findSurroundingName(offset, length); + IASTName selectedName= nodeSelector.findEnclosingName(offset, length); IASTFileLocation linkLocation= null; if (selectedName != null) { // found a name // prefer include statement over the include name @@ -96,7 +95,7 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector { } else { // search for include statement - final IASTNode cand= nodeSelector.findSurroundingNode(offset, length); + final IASTNode cand= nodeSelector.findEnclosingNode(offset, length); if (cand instanceof IASTPreprocessorIncludeStatement) { linkLocation= cand.getFileLocation(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java index f67ef8ea9d0..81ff3a5fed8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java @@ -48,7 +48,7 @@ public class PDOMSearchTextSelectionQuery extends PDOMSearchQuery { return ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_YES, monitor, new ASTRunnable() { public IStatus runOnAST(ILanguage language, IASTTranslationUnit ast) throws CoreException { if (ast != null) { - IASTName searchName= ast.getNodeSelector(null).findSurroundingName(selection.getOffset(), selection.getLength()); + IASTName searchName= ast.getNodeSelector(null).findEnclosingName(selection.getOffset(), selection.getLength()); if (searchName != null) { IBinding binding = searchName.resolveBinding(); if (binding != null) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java index c1ad3e09733..726f1888cf2 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java @@ -130,7 +130,7 @@ public class OpenDeclarationsAction extends SelectionParseAction { int selectionStart = selNode.getOffset(); int selectionLength = selNode.getLength(); - IASTName searchName= ast.getNodeSelector(null).findSurroundingName(selectionStart, selectionLength); + IASTName searchName= ast.getNodeSelector(null).findEnclosingName(selectionStart, selectionLength); if (searchName != null) { // just right, only one name selected boolean found= false; final IASTNode parent = searchName.getParent(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java index f38b19174ed..f19649659d6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java @@ -95,7 +95,7 @@ public class CMacroExpansionInput { } if (fAllowSelection) { // selection - fEnclosingNode= nodeSelector.findSurroundingNode(fTextRegion.getOffset(), fTextRegion.getLength()); + fEnclosingNode= nodeSelector.findEnclosingNode(fTextRegion.getOffset(), fTextRegion.getLength()); if (fEnclosingNode != null) { boolean macroOccurrence= false; IASTNodeLocation[] locations= fEnclosingNode.getNodeLocations(); @@ -105,7 +105,7 @@ public class CMacroExpansionInput { IASTFileLocation fileLocation= location.asFileLocation(); if (fileLocation != null && ast.getFilePath().equals(fileLocation.getFileName())) { if (fTextRegion.overlapsWith(fileLocation.getNodeOffset(), fileLocation.getNodeLength())) { - addExpansionNode(nodeSelector.findSurroundingNode(fileLocation.getNodeOffset(), fileLocation.getNodeLength())); + addExpansionNode(nodeSelector.findEnclosingNode(fileLocation.getNodeOffset(), fileLocation.getNodeLength())); macroOccurrence= true; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java index eadec3ede76..08cb386a31e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java @@ -128,7 +128,7 @@ public class CSourceHover extends AbstractCEditorTextHover implements ITextHover public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) { if (ast != null) { try { - IASTName name= ast.getNodeSelector(null).findSurroundingName(fTextRegion.getOffset(), fTextRegion.getLength()); + IASTName name= ast.getNodeSelector(null).findEnclosingName(fTextRegion.getOffset(), fTextRegion.getLength()); if (name != null) { IBinding binding= name.resolveBinding(); if (binding != null) {