From 5a0a44bf92d553aad5c5aecc8ffe518d5d5d85b0 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 9 Sep 2011 14:21:31 +0200 Subject: [PATCH] C++ function signature: Don't accidentally eat specifiers. You could accidentally delete specifiers like 'static' or 'virtual' with the 'apply function signature changes' quick fix before. Change-Id: Ia97a33f663a01063fad4d432551715ebf27a18d5 Reviewed-on: http://codereview.qt-project.org/4538 Reviewed-by: Leandro T. C. Melo --- .../cppeditor/cppfunctiondecldeflink.cpp | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp index 5b80d062a0e..a228e6a98e0 100644 --- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp +++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp @@ -430,6 +430,43 @@ static bool hasCommentedName( return commentArgNameRegexp()->indexIn(text) != -1; } +static bool canReplaceSpecifier(TranslationUnit *translationUnit, SpecifierAST *specifier) +{ + if (SimpleSpecifierAST *simple = specifier->asSimpleSpecifier()) { + switch (translationUnit->tokenAt(simple->specifier_token).kind()) { + case T_CONST: + case T_VOLATILE: + case T_CHAR: + case T_WCHAR_T: + case T_BOOL: + case T_SHORT: + case T_INT: + case T_LONG: + case T_SIGNED: + case T_UNSIGNED: + case T_FLOAT: + case T_DOUBLE: + case T_VOID: + case T_AUTO: + case T___TYPEOF__: + case T___ATTRIBUTE__: + return true; + default: + return false; + } + } + return false; +} + +static SpecifierAST *findFirstReplaceableSpecifier(TranslationUnit *translationUnit, SpecifierListAST *list) +{ + for (SpecifierListAST *it = list; it; it = it->next) { + if (canReplaceSpecifier(translationUnit, it->value)) + return it->value; + } + return 0; +} + Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffset) { Utils::ChangeSet changes; @@ -484,22 +521,25 @@ Utils::ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targ Control *control = sourceContext.control().data(); // get return type start position and declarator info from declaration - int returnTypeStart = 0; DeclaratorAST *declarator = 0; + SpecifierAST *firstReplaceableSpecifier = 0; + TranslationUnit *targetTranslationUnit = targetFile->cppDocument()->translationUnit(); if (SimpleDeclarationAST *simple = targetDeclaration->asSimpleDeclaration()) { declarator = simple->declarator_list->value; - if (simple->decl_specifier_list) - returnTypeStart = targetFile->startOf(simple->decl_specifier_list->value); - else - returnTypeStart = targetFile->startOf(declarator); + firstReplaceableSpecifier = findFirstReplaceableSpecifier( + targetTranslationUnit, simple->decl_specifier_list); } else if (FunctionDefinitionAST *def = targetDeclaration->asFunctionDefinition()) { declarator = def->declarator; - if (def->decl_specifier_list) - returnTypeStart = targetFile->startOf(def->decl_specifier_list->value); - else - returnTypeStart = targetFile->startOf(declarator); + firstReplaceableSpecifier = findFirstReplaceableSpecifier( + targetTranslationUnit, def->decl_specifier_list); } + int returnTypeStart = 0; + if (firstReplaceableSpecifier) + returnTypeStart = targetFile->startOf(firstReplaceableSpecifier); + else + returnTypeStart = targetFile->startOf(declarator); + if (!newFunction->returnType().isEqualTo(sourceFunction->returnType()) && !newFunction->returnType().isEqualTo(targetFunction->returnType())) { FullySpecifiedType type = rewriteType(newFunction->returnType(), &env, control);