OSDN Git Service

C++ function signature: Don't accidentally eat specifiers.
authorChristian Kamm <christian.d.kamm@nokia.com>
Fri, 9 Sep 2011 12:21:31 +0000 (14:21 +0200)
committerChristian Kamm <christian.d.kamm@nokia.com>
Mon, 12 Sep 2011 09:23:52 +0000 (11:23 +0200)
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 <leandro.melo@nokia.com>
src/plugins/cppeditor/cppfunctiondecldeflink.cpp

index 5b80d06..a228e6a 100644 (file)
@@ -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);