Browse Source

added option to exclude directories from being processed

stefan 1 year ago
parent
commit
ceb9fb6b1c

+ 27 - 7
metrixpp/ext/std/tools/collect.py

@@ -23,6 +23,7 @@ class Plugin(api.Plugin, api.Parent, api.IConfigurable, api.IRunable):
         self.reader = DirectoryReader()
         self.include_rules = []
         self.exclude_rules = []
+        self.exclude_dir_rules = []
         self.exclude_files = []
         self.parsers       = []
         super(Plugin, self).__init__()
@@ -37,7 +38,9 @@ class Plugin(api.Plugin, api.Parent, api.IConfigurable, api.IRunable):
         parser.add_option("--include-files", "--if", action='append',
                          help="Adds a regular expression pattern to include files in processing (files have to match any rule to be included)")
         parser.add_option("--exclude-files", "--ef", action='append',
-                         help="Adds a regular expression pattern to exclude files or directories from processing")
+                         help="Adds a regular expression pattern to exclude files or directories by name from processing")
+        parser.add_option("--exclude-directories", "--ed", action='append',
+                         help="Adds a regular expression pattern to exclude directories by path from processing")
         parser.add_option("--non-recursively", "--nr", action="store_true", default=False,
                          help="If the option is set (True), sub-directories are not processed [default: %default]")
         self.optparser = parser
@@ -65,6 +68,14 @@ class Plugin(api.Plugin, api.Parent, api.IConfigurable, api.IRunable):
                 self.optparser.error("option --exclude-files: " + str(e))
         else:
             self.add_exclude_rule(re.compile(r'^[.]'))
+
+        # check if any exclude dir rule is given
+        if options.__dict__['exclude_directories']:
+            try:
+                for exclude_dir_rule in options.__dict__['exclude_directories']:
+                    self.add_exclude_dir_rule(re.compile(exclude_dir_rule))
+            except Exception as e:
+                self.optparser.error("option --exclude-directories: " + str(e))
         self.non_recursively = options.__dict__['non_recursively']
 
     def initialize(self):
@@ -103,6 +114,9 @@ class Plugin(api.Plugin, api.Parent, api.IConfigurable, api.IRunable):
     def add_exclude_rule(self, re_compiled_pattern):
         self.exclude_rules.append(re_compiled_pattern)
 
+    def add_exclude_dir_rule(self, re_compiled_pattern):
+        self.exclude_dir_rules.append(re_compiled_pattern)
+
     def add_exclude_file(self, file_path):
         if file_path == None:
             return
@@ -113,13 +127,21 @@ class Plugin(api.Plugin, api.Parent, api.IConfigurable, api.IRunable):
         if os.path.isfile(file_name):
             for each in self.include_rules:
                 if re.match(each, os.path.basename(file_name)) != None:
-                    break;
+                    break
             # file is excluded if no include rule matches
             else:
+                logging.info("Excluding: " + file_name + " - not included by any rule")
                 return True
+        # check exclude dir rules for directories
+        if os.path.isdir(file_name):
+            for each in self.exclude_dir_rules:
+                if re.match(each, file_name) != None:
+                    logging.info("Excluding: " + file_name + " - excluded by rule '" + each.pattern + "'")
+                    return True
         # check exclude rules for both, files and directories
         for each in self.exclude_rules:
             if re.match(each, os.path.basename(file_name)) != None:
+                logging.info("Excluding: " + file_name + " - excluded by rule '" + each.pattern + "'")
                 return True
         # finally check if a file is excluded directly
         for each in self.exclude_files:
@@ -257,7 +279,7 @@ class DirectoryReader():
                 return default
 
             # no valid UTF8 byte sequence:
-            return default;
+            return default
           # end of checkforUTF8 ------------------------------------------------
 
         # ----------------------------------------------------------------------
@@ -267,8 +289,8 @@ class DirectoryReader():
         # - Phyton 3: "a" is a binary array
         # - Python 2: "a" is string array!
         # ----------------------------------------------------------------------
-        f = open(filename, 'rb');
-        a = f.read();
+        f = open(filename, 'rb')
+        a = f.read()
         f.close()
 
         # check for codings with BOM:
@@ -355,8 +377,6 @@ class DirectoryReader():
                         db_loader.save_file_data(data)
                         #logging.debug("-" * 60)
                         exit_code += procerrors
-            else:
-                logging.info("Excluding: " + norm_path)
             return exit_code
 
 

+ 18 - 0
metrixpp/tests/general/test_basic.py

@@ -213,6 +213,24 @@ class Test(tests.common.TestCase):
         runner = tests.common.ToolRunner('export', ['--help'])
         self.assertExec(runner.run())
 
+    def test_exclusion(self):
+
+        runner = tests.common.ToolRunner('collect',
+                                         ['--std.code.complexity.cyclomatic',
+                                          '--exclude-files=simple_excluded'],
+                                         prefix='excluding-unused',
+                                         check_stderr=[(0, -1)],
+                                         cwd="sources_exclude")
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('collect',
+                                         ['--std.code.complexity.cyclomatic',
+                                          '--exclude-directories=.*\/excluded'],
+                                         prefix='excluding-directories',
+                                         check_stderr=[(0, -1)],
+                                         cwd="sources_exclude")
+        self.assertExec(runner.run())
+
     def test_view_format(self):
         
         # note: --scope-mode is tested in workflow test above

+ 89 - 0
metrixpp/tests/general/test_basic/sources_exclude/excluded/simple_excluded.cpp

@@ -0,0 +1,89 @@
+
+
+// Just produce any code in order to test basic workflow
+namespace hmm
+{
+
+#define old_prep
+
+class A
+{
+
+	A()
+	{
+		/* first funtion */
+		this->m_me88er = 10;
+		if (a & b)
+		{
+			for (int i = 0; i < 0 && i > 0; i++)
+			{
+				int a; // right?
+			}
+		}
+	}
+
+
+	int func(int param = 5)
+	{
+		class embeded
+		{
+			embeded()
+			{
+				int a = 10;
+				if (true)
+				{
+					// again crazy
+				}
+			}
+		};
+		if (a);
+	}
+
+	int func_to_be_removed_in_new_sources(int param = 5)
+	{
+		class embeded
+		{
+			embeded()
+			{
+				int a = 10;
+				if ("text")
+				{
+					/* again crazy */
+				}
+			}
+		};
+		if (a && b);
+	}
+
+	int never(int how_long = 999)
+	{
+		while(true)
+		{
+
+		}
+		return 1;
+	}
+
+    virtual int pure_virtual_method() = 0;
+    int pure_virtual_overrider() override = 0;
+
+	int m_me88er = 10;
+
+    int hex_number = 0xaBc78;
+    unsigned int binary_number = 0b00110u;
+    unsigned long long int octal_number = 074uLL;
+    unsigned long long int different_order = 123llU;
+    long int just_l = 42l;
+    int one_separator = 123'456;
+    int two_separators = 123'456'789;
+
+    constexpr int const_hex_number = 0xaBc78;
+    const unsigned int const_binary_number = 0b00110u;
+    const unsigned long long int const_octal_number = 074uLL;
+    const unsigned long long int const_different_order = 123llU;
+    const long int const_just_l = 42l;
+    constexpr int one_separator = 123'456;
+    const int two_separators = 123'456'789;
+};
+
+}

+ 89 - 0
metrixpp/tests/general/test_basic/sources_exclude/simple.cpp

@@ -0,0 +1,89 @@
+
+
+// Just produce any code in order to test basic workflow
+namespace hmm
+{
+
+#define old_prep
+
+class A
+{
+
+	A()
+	{
+		/* first funtion */
+		this->m_me88er = 10;
+		if (a & b)
+		{
+			for (int i = 0; i < 0 && i > 0; i++)
+			{
+				int a; // right?
+			}
+		}
+	}
+
+
+	int func(int param = 5)
+	{
+		class embeded
+		{
+			embeded()
+			{
+				int a = 10;
+				if (true)
+				{
+					// again crazy
+				}
+			}
+		};
+		if (a);
+	}
+
+	int func_to_be_removed_in_new_sources(int param = 5)
+	{
+		class embeded
+		{
+			embeded()
+			{
+				int a = 10;
+				if ("text")
+				{
+					/* again crazy */
+				}
+			}
+		};
+		if (a && b);
+	}
+
+	int never(int how_long = 999)
+	{
+		while(true)
+		{
+
+		}
+		return 1;
+	}
+
+    virtual int pure_virtual_method() = 0;
+    int pure_virtual_overrider() override = 0;
+
+	int m_me88er = 10;
+
+    int hex_number = 0xaBc78;
+    unsigned int binary_number = 0b00110u;
+    unsigned long long int octal_number = 074uLL;
+    unsigned long long int different_order = 123llU;
+    long int just_l = 42l;
+    int one_separator = 123'456;
+    int two_separators = 123'456'789;
+
+    constexpr int const_hex_number = 0xaBc78;
+    const unsigned int const_binary_number = 0b00110u;
+    const unsigned long long int const_octal_number = 074uLL;
+    const unsigned long long int const_different_order = 123llU;
+    const long int const_just_l = 42l;
+    constexpr int one_separator = 123'456;
+    const int two_separators = 123'456'789;
+};
+
+}

+ 4 - 0
metrixpp/tests/general/test_basic/test_exclusion_collect_excluding-directories_stderr.gold.txt

@@ -0,0 +1,4 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Excluding: ./excluded - excluded by rule '.*\/excluded'
+[LOG]: INFO:	Processing: ./simple.cpp
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 0 - 0
metrixpp/tests/general/test_basic/test_exclusion_collect_excluding-directories_stdout.gold.txt


+ 4 - 0
metrixpp/tests/general/test_basic/test_exclusion_collect_excluding-unused_stderr.gold.txt

@@ -0,0 +1,4 @@
+[LOG]: WARNING:	Logging enabled with INFO level
+[LOG]: INFO:	Excluding: ./excluded/simple_excluded.cpp - excluded by rule 'simple_excluded'
+[LOG]: INFO:	Processing: ./simple.cpp
+[LOG]: WARNING:	Done (1 seconds). Exit code: 0

+ 0 - 0
metrixpp/tests/general/test_basic/test_exclusion_collect_excluding-unused_stdout.gold.txt


+ 4 - 1
metrixpp/tests/general/test_basic/test_help_collect_default_stdout.gold.txt

@@ -151,7 +151,10 @@ Options:
                         included)
   --exclude-files=EXCLUDE_FILES, --ef=EXCLUDE_FILES
                         Adds a regular expression pattern to exclude files or
-                        directories from processing
+                        directories by name from processing
+  --exclude-directories=EXCLUDE_DIRECTORIES, --ed=EXCLUDE_DIRECTORIES
+                        Adds a regular expression pattern to exclude
+                        directories by path from processing
   --non-recursively, --nr
                         If the option is set (True), sub-directories are not
                         processed [default: False]

+ 1 - 1
metrixpp/tests/general/test_basic/test_std_maintindex_collect_default_stderr.gold.txt

@@ -1,5 +1,5 @@
 [LOG]: WARNING:	Logging enabled with INFO level
-[LOG]: INFO:	Excluding: ./.unused.cpp
+[LOG]: INFO:	Excluding: ./.unused.cpp - excluded by rule '^[.]'
 [LOG]: INFO:	Skipping: ./dummy.txt
 [LOG]: INFO:	Processing: ./file_deleted_in_new_sources.cpp
 [LOG]: INFO:	Processing: ./simple.cpp

+ 1 - 1
metrixpp/tests/general/test_basic/test_workflow_collect_default_stderr.gold.txt

@@ -1,5 +1,5 @@
 [LOG]: WARNING:	Logging enabled with INFO level
-[LOG]: INFO:	Excluding: ./.unused.cpp
+[LOG]: INFO:	Excluding: ./.unused.cpp - excluded by rule '^[.]'
 [LOG]: INFO:	Skipping: ./dummy.txt
 [LOG]: INFO:	Processing: ./file_deleted_in_new_sources.cpp
 [LOG]: INFO:	Processing: ./simple.cpp

+ 1 - 1
metrixpp/tests/general/test_basic/test_workflow_collect_second_stderr.gold.txt

@@ -1,5 +1,5 @@
 [LOG]: WARNING:	Logging enabled with INFO level
-[LOG]: INFO:	Excluding: ./.unused.cpp
+[LOG]: INFO:	Excluding: ./.unused.cpp - excluded by rule '^[.]'
 [LOG]: INFO:	Processing: ./simple.cpp
 [LOG]: INFO:	Processing: ./simple2.cpp
 [LOG]: WARNING:	Done (1 seconds). Exit code: 0