[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58466] trunk/blender/source/tools/ check_style_c.py: style checker now checks each block ends with break/ return/goto/continue or comment /* fall-through */

Campbell Barton ideasman42 at gmail.com
Sun Jul 21 10:20:33 CEST 2013


Revision: 58466
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58466
Author:   campbellbarton
Date:     2013-07-21 08:20:33 +0000 (Sun, 21 Jul 2013)
Log Message:
-----------
style checker now checks each block ends with break/return/goto/continue or comment /* fall-through */
shows up some suspicious code and false positive rate isnt too bad.

Modified Paths:
--------------
    trunk/blender/source/tools/check_style_c.py

Modified: trunk/blender/source/tools/check_style_c.py
===================================================================
--- trunk/blender/source/tools/check_style_c.py	2013-07-21 08:16:37 UTC (rev 58465)
+++ trunk/blender/source/tools/check_style_c.py	2013-07-21 08:20:33 UTC (rev 58466)
@@ -83,8 +83,11 @@
         self.line = line
 
 
-def tk_range_to_str(a, b):
-    return "".join([tokens[i].text for i in range(a, b + 1)])
+def tk_range_to_str(a, b, expand_tabs=False):
+    txt = "".join([tokens[i].text for i in range(a, b + 1)])
+    if expand_tabs:
+        txt = txt.expandtabs(TAB_SIZE)
+    return txt
 
 
 def tk_item_is_newline(tok):
@@ -172,10 +175,6 @@
     return tokens[index_prev].line < tokens[index].line
 
 
-def extract_text(index_start, index_end):
-    return "".join(tokens[i].text for i in range(index_start, index_end))
-
-
 def extract_to_linestart(index):
     ls = []
     line = tokens[index].line
@@ -307,7 +306,7 @@
     else:
         print("%s:%d: warning: %s" % (filepath, tokens[index_kw_start].line, message))
         if WARN_TEXT:
-            print("".join([tokens[i].text for i in range(index_kw_start, index_kw_end + 1)]))
+            print(tk_range_to_str(index_kw_start, index_kw_end, expand_tabs=True))
 
 
 def warning_lineonly(message, line):
@@ -438,29 +437,92 @@
     if tokens[index_next].type == Token.Punctuation and tokens[index_next].text == "{":
         ws_switch_indent = extract_to_linestart(index_kw)
 
-        # TODO, check case statement has a break, return or /* fall-through */
-
         if ws_switch_indent.isspace():
 
             # 'case' should have at least 1 indent.
             # otherwise expect 2 indent (or more, for nested switches)
             ws_test = {
                 "case": ws_switch_indent + "\t",
-                "default": ws_switch_indent + "\t",
+                "default:": ws_switch_indent + "\t",
+
                 "break": ws_switch_indent + "\t\t",
                 "return": ws_switch_indent + "\t\t",
+                "continue": ws_switch_indent + "\t\t",
+                "goto": ws_switch_indent + "\t\t",
                 }
 
             index_final = tk_match_backet(index_next)
 
+            case_ls = []
+
             for i in range(index_next + 1, index_final):
-                if tokens[i].type == Token.Keyword:
-                    if tokens[i].text in {"case", "break", "return"}:
+                # 'default' is seen as a label
+                # print(tokens[i].type, tokens[i].text)
+                if tokens[i].type in {Token.Keyword, Token.Name.Label}:
+                    if tokens[i].text in {"case", "default:", "break", "return", "comtinue", "goto"}:
                         ws_other_indent = extract_to_linestart(i)
                         # non ws start - we ignore for now, allow case A: case B: ...
                         if ws_other_indent.isspace():
-                            if not ws_other_indent.startswith(ws_test[tokens[i].text]):
+                            ws_test_other = ws_test[tokens[i].text]
+                            if not ws_other_indent.startswith(ws_test_other):
                                 warning("%s is not indented enough" % tokens[i].text, i, i)
+
+                            # assumes correct indentation...
+                            if tokens[i].text in {"case", "default:"}:
+                                if ws_other_indent == ws_test_other:
+                                    case_ls.append(i)
+
+            case_ls.append(index_final - 1)
+
+            # detect correct use of break/return
+            for j in range(len(case_ls) - 1):
+                i_case = case_ls[j]
+                i_end = case_ls[j + 1]
+
+                # detect cascading cases, check there is one line inbetween at least
+                if tokens[i_case].line + 1 < tokens[i_end].line:
+                    ok = False
+
+                    # scan case body backwards
+                    for i in reversed(range(i_case, i_end)):
+                        if tokens[i].type == Token.Punctuation:
+                            if tokens[i].text == "}":
+                                ws_other_indent = extract_to_linestart(i)
+                                if ws_other_indent != ws_test["case"]:
+                                    # break/return _not_ found
+                                    break
+
+                        elif tokens[i].type in Token.Comment:
+                            if tokens[i].text == "/* fall-through */":
+                                ok = True
+                                break
+                            else:
+                                #~ print("Commment '%s'" % tokens[i].text)
+                                pass
+
+
+                        elif tokens[i].type == Token.Keyword:
+                            if tokens[i].text in {"break", "return", "continue", "goto"}:
+                                if tokens[i_case].line == tokens[i].line:
+                                    # Allow for...
+                                    #     case BLAH: var = 1; break;
+                                    # ... possible there is if statements etc, but assume not
+                                    ok = True
+                                    break
+                                else:
+                                    ws_other_indent = extract_to_linestart(i)
+                                    ws_other_indent = ws_other_indent[:len(ws_other_indent) - len(ws_other_indent.lstrip())]
+                                    ws_test_other = ws_test[tokens[i].text]
+                                    if ws_other_indent == ws_test_other:
+                                        ok = True
+                                        break
+                                    else:
+                                        print("indent mismatch...")
+                                        print("'%s'" % ws_other_indent)
+                                        print("'%s'" % ws_test_other)
+                    if not ok:
+                        warning("case/default statement has no break", i_case, i_end)
+                        #~ print(tk_range_to_str(i_case - 1, i_end - 1, expand_tabs=True))
         else:
             warning("switch isn't the first token in the line", index_kw_start, index_kw_end)
     else:
@@ -636,9 +698,8 @@
 
 def blender_check_linelength(index_start, index_end, length):
     if length > LIN_SIZE:
-        text = "".join([tokens[i].text for i in range(index_start, index_end + 1)])
+        text = tk_range_to_str(index_start, index_end, expand_tabs=True)
         for l in text.split("\n"):
-            l = l.expandtabs(TAB_SIZE)
             if len(l) > LIN_SIZE:
                 warning("line length %d > %d" % (len(l), LIN_SIZE), index_start, index_end)
 
@@ -724,7 +785,7 @@
         #        3, 4}
         # ... so only check braces which are the first text
         if ws_i_match.isspace():
-	        ws_i = extract_to_linestart(i)
+            ws_i = extract_to_linestart(i)
             ws_i_match_lstrip = ws_i_match.lstrip()
 
             ws_i = ws_i[:len(ws_i) - len(ws_i.lstrip())]




More information about the Bf-blender-cvs mailing list