From a834796fa80004fd93a9e8bde7442818f48fd2f5 Mon Sep 17 00:00:00 2001 From: Thomas Corbat Date: Thu, 22 Jun 2017 13:20:47 +0200 Subject: [PATCH] Bug 518628 Function declarator location misses virtual specifiers - Change parser to include virtual specifier in function declarator location - Change DeclaratorWriter to write all virtual specifiers in their initial order Change-Id: Iff381394b834146c1b63877bc9eb84517d31e078 (cherry picked from commit 65eda42b163bd58465f88ffb93135404b3444659) --- .../parser/tests/ast2/DOMLocationTests.java | 26 ++++++++++++- .../rewrite/changegenerator/ReplaceTests.java | 39 +++++++++++++++++++ .../dom/parser/cpp/GNUCPPSourceParser.java | 23 ++++++----- .../rewrite/astwriter/DeclaratorWriter.java | 24 ++++++++---- 4 files changed, 93 insertions(+), 19 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java index 96d7f26f1d7..6136c3b48f1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationTests.java @@ -13,6 +13,8 @@ package org.eclipse.cdt.core.parser.tests.ast2; import junit.framework.TestSuite; +import java.util.Arrays; + import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; @@ -673,5 +675,27 @@ public class DOMLocationTests extends AST2TestBase { assertEquals("test", templateIdName.getRawSignature()); //$NON-NLS-1$ } - + + // struct Base { + // virtual void func1(); + // virtual void func2(); + // virtual void func3(); + // virtual void func4(); + // }; + // struct Sub : Base { + // void func1() final; + // void func2() override; + // void func3() final override; + // void func4() override final; + // }; + public void testFunctionDeclaratorLocationContainsVirtualSpecifiers_Bug518628() throws Exception { + String testCode = getAboveComment(); + BindingAssertionHelper assertionHelper = getAssertionHelper(ParserLanguage.CPP); + String[] funcDeclaratorSignatures = new String[]{"func1() final", "func2() override", "func3() final override", "func4() override final"}; + Arrays.stream(funcDeclaratorSignatures).forEach(signature -> { + IASTNode func1Declarator = assertionHelper.assertNode(signature, ICPPASTFunctionDeclarator.class); + assertFileLocation(func1Declarator, testCode, signature); + + }); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/ReplaceTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/ReplaceTests.java index 4a04c4f5a2e..2c8a3c19cd5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/ReplaceTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/ReplaceTests.java @@ -979,4 +979,43 @@ public class ReplaceTests extends ChangeGeneratorTest { } }); } + + //struct B { + // virtual void func1(); + // virtual void func2(); + // virtual void func3(); + // virtual void func4(); + //}; + //struct S : B{ + // void func1() final; + // void func2() override; + // void func3() override final; + // void func4() final override; + //}; + + //struct B { + // virtual void func1(); + // virtual void func2(); + // virtual void func3(); + // virtual void func4(); + //}; + //struct S : B{ + // void func1() final; + // void func2() override; + // void func3() override final; + // void func4() final override; + //}; + public void testReplaceFunctionDeclaratorWithVirtualSpecifier_Bug518628() throws Exception { + compareResult(new ASTVisitor() { + { + shouldVisitDeclarators = true; + } + + @Override + public int visit(IASTDeclarator declarator) { + addModification(null, ModificationKind.REPLACE, declarator, declarator.copy()); + return PROCESS_SKIP; + } + }); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 46ea9c12431..280fe8f63a7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -143,6 +143,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier.SpecifierKind; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; @@ -3862,21 +3863,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { while (true) { IToken token = LAcatchEOF(1); ContextSensitiveTokenType contextSensitiveType = getContextSensitiveType(token); + if (contextSensitiveType == null) { + break; + } + consume(); + SpecifierKind specifierKind; if (contextSensitiveType == ContextSensitiveTokenType.OVERRIDE) { - consume(); - ICPPASTVirtSpecifier spec = getNodeFactory().newVirtSpecifier( - ICPPASTVirtSpecifier.SpecifierKind.Override); - setRange(spec, token.getOffset(), token.getOffset() + token.getLength()); - typeRelevantDtor.addVirtSpecifier(spec); + specifierKind = ICPPASTVirtSpecifier.SpecifierKind.Override; } else if (contextSensitiveType == ContextSensitiveTokenType.FINAL) { - consume(); - ICPPASTVirtSpecifier spec = getNodeFactory().newVirtSpecifier( - ICPPASTVirtSpecifier.SpecifierKind.Final); - setRange(spec, token.getOffset(), token.getOffset() + token.getLength()); - typeRelevantDtor.addVirtSpecifier(spec); + specifierKind = ICPPASTVirtSpecifier.SpecifierKind.Final; } else { break; } + ICPPASTVirtSpecifier spec = getNodeFactory().newVirtSpecifier(specifierKind); + int endOffset = token.getOffset() + token.getLength(); + setRange(spec, token.getOffset(), endOffset); + typeRelevantDtor.addVirtSpecifier(spec); + adjustEndOffset(typeRelevantDtor, endOffset); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java index 78164716c7a..d331033c49a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java @@ -35,6 +35,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator.RefQualifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier.SpecifierKind; import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; @@ -161,14 +163,7 @@ public class DeclaratorWriter extends NodeWriter { scribe.printSpace(); scribe.print(Keywords.MUTABLE); } - if (funcDec.isOverride()) { - scribe.printSpace(); - scribe.print(Keywords.cOVERRIDE); - } - if (funcDec.isFinal()) { - scribe.printSpace(); - scribe.print(Keywords.cFINAL); - } + writeVirtualSpecifiers(funcDec); if (funcDec.isPureVirtual()) { scribe.print(PURE_VIRTUAL); } @@ -182,6 +177,19 @@ public class DeclaratorWriter extends NodeWriter { } } + public void writeVirtualSpecifiers(ICPPASTFunctionDeclarator funcDec) { + for (ICPPASTVirtSpecifier virtSpecifier : funcDec.getVirtSpecifiers()) { + scribe.printSpace(); + SpecifierKind specifierKind = virtSpecifier.getKind(); + if (specifierKind == SpecifierKind.Override) { + scribe.print(Keywords.cOVERRIDE); + } + if (specifierKind == SpecifierKind.Final) { + scribe.print(Keywords.cFINAL); + } + } + } + protected void writeExceptionSpecification(ICPPASTFunctionDeclarator funcDec, IASTTypeId[] exceptions, ICPPASTExpression noexceptExpression) { if (exceptions != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) {