Nitsmell : Adding new code smells and print console updated
authorFlorian Deljarry <deljarry.florian@gmail.com>
Fri, 23 Jun 2017 15:17:24 +0000 (11:17 -0400)
committerFlorian Deljarry <deljarry.florian@gmail.com>
Wed, 2 Aug 2017 17:00:07 +0000 (13:00 -0400)
Add :
- New "no abstract implementation" code smell
- Toolcontext option to print one by one a detected codesmell
Update :
- Print console improve
- Feature envy codesmell prepose a move help

Signed-off-by: Florian Deljarry <deljarry.florian@gmail.com>

18 files changed:
src/metrics/codesmells_metrics.nit
src/metrics/mclassdef_collect.nit
src/metrics/method_analyze_metrics.nit
src/metrics/nitsmell_toolcontext.nit [new file with mode: 0644]
src/nitsmells.nit
tests/TestNitsmells/LargeClass/largeclass.nit
tests/TestNitsmells/LongMethod/longmethod.nit
tests/TestNitsmells/LongParameterList/longparameterlist.nit
tests/TestNitsmells/NoAbstractImplemented/longparameterlist.nit [new file with mode: 0644]
tests/nitsmells.args
tests/sav/nitsmells_args1.res
tests/sav/nitsmells_args2.res
tests/sav/nitsmells_args3.res
tests/sav/nitsmells_args4.res
tests/sav/nitsmells_args5.res [new file with mode: 0644]
tests/sav/nitsmells_args6.res [new file with mode: 0644]
tests/sav/nitsmells_args7.res [new file with mode: 0644]
tests/sav/nitsmells_args8.res [new file with mode: 0644]

index d09e769..e335d8f 100644 (file)
@@ -16,9 +16,7 @@
 module codesmells_metrics
 
 import frontend
-import metrics_base
-import mclasses_metrics
-import semantize
+import nitsmell_toolcontext
 import method_analyze_metrics
 import mclassdef_collect
 
@@ -43,7 +41,11 @@ class CodeSmellsMetricsPhase
                for mclass in mainmodule.flatten_mclass_hierarchy do
                        mclass_codesmell.collect(mclass.mclassdefs,self)
                end
-               mclass_codesmell.print_top(10)
+               if toolcontext.opt_get_all.value then
+                       mclass_codesmell.print_all
+               else
+                       mclass_codesmell.print_top(10)
+               end
        end
 
        fun set_all_average_metrics do
@@ -60,22 +62,21 @@ class BadConceptonController
        # Code smell list
        var bad_conception_elements = new Array[BadConceptionFinder]
 
-       # Print all element conception
+       # Print all collected code smell sort in decroissant order
        fun print_all do
-               for bad_conception in bad_conception_elements do
-                       bad_conception.print_all
+               for bad_conception in self.sort do
+                       bad_conception.print_collected_data
                end
        end
 
-       # Print number of top element conception
+       # Print the n top element
        fun print_top(number: Int) do
-               var test = self.get_numbers_of_elements(number)
-               for bad_conception in test do
-                       bad_conception.print_all
+               for bad_conception in self.get_numbers_of_elements(number) do
+                       bad_conception.print_collected_data
                end
        end
 
-       # Collection
+       # Collect method take Array of mclassdef to find the code smells for every class
        fun collect(mclassdefs: Array[MClassDef],phase: CodeSmellsMetricsPhase) do
                for mclassdef in mclassdefs do
                        var bad_conception_class = new BadConceptionFinder(mclassdef,phase)
@@ -84,6 +85,7 @@ class BadConceptonController
                end
        end
 
+       # Sort the bad_conception_elements array
        fun sort: Array[BadConceptionFinder]
        do
                var res = bad_conception_elements
@@ -92,6 +94,7 @@ class BadConceptonController
                return res
        end
 
+       # Return an array with n elements
        fun get_numbers_of_elements(number : Int) : Array[BadConceptionFinder]do
                var return_values = new Array[BadConceptionFinder]
                var list = self.sort
@@ -109,32 +112,49 @@ class BadConceptionFinder
        var mclassdef: MClassDef
        var array_badconception = new Array[BadConception]
        var phase: CodeSmellsMetricsPhase
+       var score = 0.0
 
+       # Collect code smell with selected toolcontext option
        fun collect do
                var bad_conception_elements = new Array[BadConception]
-               bad_conception_elements.add(new LargeClass(phase))
-               bad_conception_elements.add(new LongParameterList(phase))
-               bad_conception_elements.add(new FeatureEnvy(phase))
-               bad_conception_elements.add(new LongMethod(phase))
+               # Check toolcontext option
+               if phase.toolcontext.opt_feature_envy.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new FeatureEnvy(phase))
+               if phase.toolcontext.opt_long_method.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongMethod(phase))
+               if phase.toolcontext.opt_long_params.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongParameterList(phase))
+               if phase.toolcontext.opt_no_abstract_implementation.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new NoAbstractImplementation(phase))
+               if phase.toolcontext.opt_large_class.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LargeClass(phase))
+               # Collected all code smell if their state is true
                for bad_conception_element in bad_conception_elements do
                        if bad_conception_element.collect(self.mclassdef,phase.toolcontext.modelbuilder) then array_badconception.add(bad_conception_element)
                end
+               # Compute global score
+               collect_global_score
        end
 
-       fun print_all do
+       fun print_collected_data do
                if array_badconception.length != 0 then
-                       print "-----------"
-                       print "{mclassdef.full_name}"
+                       print "--------------------"
+                       print phase.toolcontext.format_h1("Full name: {mclassdef.full_name} Location: {mclassdef.location}")
                        for bad_conception in array_badconception do
                                bad_conception.print_result
                        end
                end
        end
+
+       fun collect_global_score do
+               if array_badconception.not_empty then
+                       for bad_conception in array_badconception do
+                               self.score += bad_conception.score
+                       end
+               end
+       end
 end
 
-class BadConception
+abstract class BadConception
        var phase: CodeSmellsMetricsPhase
 
+       var score = 0.0
+
        # Name
        fun name: String is abstract
 
@@ -146,6 +166,11 @@ class BadConception
 
        # Show results in console
        fun print_result is abstract
+
+       # Compute code smell score to sort
+       fun score_rate do
+               score = 1.0
+       end
 end
 
 class LargeClass
@@ -159,15 +184,20 @@ class LargeClass
        redef fun desc do return "Large class"
 
        redef fun collect(mclassdef, model_builder): Bool do
-               number_attribut = mclassdef.collect_intro_and_redef_mattributes(model_builder.model.private_view).length
-               # get the number of methods (subtract the get and set of attibutes with (numberAtribut*2))
-               number_method = mclassdef.collect_intro_and_redef_methods(model_builder.model.private_view).length
-               return number_method.to_f > phase.average_number_of_method and number_attribut.to_f > phase.average_number_of_attribute
+               self.number_attribut = mclassdef.collect_intro_and_redef_mattributes(model_builder.model.private_view).length
+               # Get the number of methods (Accessor include) (subtract the get and set of attibutes with (numberAtribut*2))
+               self.number_method = mclassdef.collect_intro_and_redef_methods(model_builder.model.private_view).length
+               self.score_rate
+               return self.number_method.to_f > phase.average_number_of_method and self.number_attribut.to_f > phase.average_number_of_attribute
        end
 
        redef fun print_result do
                print phase.toolcontext.format_h2("{desc}: {number_attribut} attributes and {number_method} methods ({phase.average_number_of_attribute}A {phase.average_number_of_method}M Average)")
        end
+
+       redef fun score_rate do
+               score = (number_method.to_f + number_attribut.to_f) / (phase.average_number_of_method + phase.average_number_of_attribute)
+       end
 end
 
 class LongParameterList
@@ -180,26 +210,35 @@ class LongParameterList
 
        redef fun collect(mclassdef, model_builder): Bool do
                for meth in mclassdef.collect_intro_and_redef_mpropdefs(model_builder.model.private_view) do
-                       # check if the property is a method definition
+                       var threshold_value = 4
+                       # Get the threshold value from the toolcontext command
+                       if phase.toolcontext.opt_long_params_threshold.value != 0 then threshold_value = phase.toolcontext.opt_long_params_threshold.value
+                       # Check if the property is a method definition
                        if not meth isa MMethodDef then continue
                        # Check if method has a signature
                        if meth.msignature == null then continue
-                       if meth.msignature.mparameters.length <= 4 then continue
-                       bad_methods.add(meth)
+                       if meth.msignature.mparameters.length <= threshold_value then continue
+                       self.bad_methods.add(meth)
                end
-               return bad_methods.not_empty
+               self.score_rate
+               return self.bad_methods.not_empty
        end
 
-
        redef fun print_result do
-               print "{desc}:"
-               if bad_methods.length >= 1 then
+               print phase.toolcontext.format_h2("{desc}:")
+               if self.bad_methods.not_empty then
                        print " Affected method(s):"
-                       for method in bad_methods do
+                       for method in self.bad_methods do
                                print "         -{method.name} has {method.msignature.mparameters.length} parameters"
                        end
                end
        end
+
+       redef fun score_rate do
+               if self.bad_methods.not_empty then
+                       self.score = self.bad_methods.length.to_f/ phase.average_number_of_method
+               end
+       end
 end
 
 class FeatureEnvy
@@ -213,21 +252,38 @@ class FeatureEnvy
        redef fun collect(mclassdef, model_builder): Bool do
                var mmethoddefs = call_analyze_methods(mclassdef,model_builder)
                for mmethoddef in mmethoddefs do
-                       if mmethoddef.total_extern_call <= mmethoddef.total_self_call then continue
-                       bad_methods.add(mmethoddef)
+                       var max_class_call = mmethoddef.class_call.max
+                       # Check if the class with the maximum call is >= auto-call and the maximum call class is != of this class
+                       if mmethoddef.class_call[max_class_call] <= mmethoddef.total_self_call or max_class_call.mclass.full_name == mclassdef.mclass.full_name then continue
+                       self.bad_methods.add(mmethoddef)
                end
-               return bad_methods.not_empty
+               self.score_rate
+               return self.bad_methods.not_empty
        end
 
        redef fun print_result do
-               print "{desc}:"
-               if bad_methods.length >= 1 then
+               print phase.toolcontext.format_h2("{desc}:")
+               if self.bad_methods.not_empty then
                        print " Affected method(s):"
-                       for method in bad_methods do
-                               print "         -{method.name} {method.total_self_call}/{method.total_call}"
+                       for method in self.bad_methods do
+                               var max_class_call = method.class_call.max
+                               if max_class_call != null then
+                                       # Check if the type of max call class is generique
+                                       if max_class_call.mclass.mclass_type isa MGenericType and not phase.toolcontext.opt_move_generics.value then
+                                               print "         -{method.name}({method.msignature.mparameters.join(", ")}) {method.total_self_call}/{method.class_call[max_class_call]}"
+                                       else
+                                               print "         -{method.name}({method.msignature.mparameters.join(", ")}) {method.total_self_call}/{method.class_call[max_class_call]} move to {max_class_call}"
+                                       end
+                               end
                        end
                end
        end
+
+       redef fun score_rate do
+               if self.bad_methods.not_empty then
+                       self.score = self.bad_methods.length.to_f / phase.average_number_of_method
+               end
+       end
 end
 
 class LongMethod
@@ -240,22 +296,68 @@ class LongMethod
 
        redef fun collect(mclassdef, model_builder): Bool do
                var mmethoddefs = call_analyze_methods(mclassdef,model_builder)
+               var threshold_value = phase.average_number_of_lines.to_i
+               # Get the threshold value from the toolcontext command
+               if phase.toolcontext.opt_long_method_threshold.value != 0 then threshold_value = phase.toolcontext.opt_long_method_threshold.value
+
                for mmethoddef in mmethoddefs do
-                       if mmethoddef.line_number <= phase.average_number_of_lines.to_i then continue
-                       bad_methods.add(mmethoddef)
+                       if mmethoddef.line_number <= threshold_value then continue
+                       self.bad_methods.add(mmethoddef)
                end
-               return bad_methods.not_empty
+               self.score_rate
+               return self.bad_methods.not_empty
        end
 
        redef fun print_result do
-               print "{desc}:  Average {phase.average_number_of_lines.to_i} lines"
-               if bad_methods.length >= 1 then
+               print phase.toolcontext.format_h2("{desc}:  Average {phase.average_number_of_lines.to_i} lines")
+               if self.bad_methods.not_empty then
                        print " Affected method(s):"
-                       for method in bad_methods do
+                       for method in self.bad_methods do
                                print "         -{method.name} has {method.line_number} lines"
                        end
                end
        end
+
+       redef fun score_rate do
+               if self.bad_methods.not_empty then
+                       self.score = self.bad_methods.length.to_f / phase.average_number_of_method
+               end
+       end
+end
+
+class NoAbstractImplementation
+       super BadConception
+       var bad_methods = new Array[MMethodDef]
+
+       redef fun name do return "LONGMETH"
+
+       redef fun desc do return "No Implemented abstract property"
+
+       redef fun collect(mclassdef, model_builder): Bool do
+               if not mclassdef.mclass.is_abstract and not mclassdef.mclass.is_interface then
+                       if mclassdef.collect_abstract_methods(model_builder.model.private_view).not_empty then
+                               bad_methods.add_all(mclassdef.collect_not_define_properties(model_builder.model.private_view))
+                       end
+               end
+               self.score_rate
+               return bad_methods.not_empty
+       end
+
+       redef fun print_result do
+               print phase.toolcontext.format_h2("{desc}:")
+               if self.bad_methods.not_empty then
+                       print " Affected method(s):"
+                       for method in self.bad_methods do
+                               print "         -{method.name}"
+                       end
+               end
+       end
+
+       redef fun score_rate do
+               if self.bad_methods.not_empty then
+                       self.score = self.bad_methods.length.to_f / phase.average_number_of_method
+               end
+       end
 end
 
 redef class ModelView
@@ -313,5 +415,11 @@ end
 class BadConceptionComparator
        super Comparator
        redef type COMPARED: BadConceptionFinder
-       redef fun compare(a,b) do return a.array_badconception.length <=> b.array_badconception.length
+       redef fun compare(a,b) do
+               var test = a.array_badconception.length <=> b.array_badconception.length
+               if test == 0 then
+                       return a.score <=> b.score
+               end
+               return a.array_badconception.length <=> b.array_badconception.length
+       end
 end
index 5b6c937..84537ce 100644 (file)
@@ -121,6 +121,7 @@ redef class MClassDef
                return res
        end
 
+       # Collect all mmethod inehrited,intro and redef
        fun collect_all_methods(view: ModelView): Set[MMethod] do
                var set = new HashSet[MMethod]
                set.add_all collect_intro_mmethods(view)
@@ -129,6 +130,7 @@ redef class MClassDef
                return set
        end
 
+       # Collect all mattributs inehrited,intro and redef
        fun collect_all_mattributes(view: ModelView): Set[MAttribute] do
                var set = new HashSet[MAttribute]
                set.add_all collect_redef_mattributes(view)
@@ -137,6 +139,7 @@ redef class MClassDef
                return set
        end
 
+       # Collect intro and redef mmethods
        fun collect_intro_and_redef_methods(view: ModelView): Set[MMethod] do
                var set = new HashSet[MMethod]
                set.add_all collect_intro_mmethods(view)
@@ -144,6 +147,7 @@ redef class MClassDef
                return set
        end
 
+       # Collect intro and redef mattributs
        fun collect_intro_and_redef_mattributes(view: ModelView): Set[MAttribute] do
                var set = new HashSet[MAttribute]
                set.add_all collect_redef_mattributes(view)
@@ -151,17 +155,37 @@ redef class MClassDef
                return set
        end
 
-       fun collect_intro_and_redef_mproperties(view: ModelView): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               set.add_all collect_redef_mproperties(view)
-               set.add_all collect_intro_mproperties(view)
-               return set
-       end
-
+       # Collect intro and redef mpropdefs
        fun collect_intro_and_redef_mpropdefs(view: ModelView): Set[MPropDef] do
                var set = new HashSet[MPropDef]
                set.add_all collect_intro_mpropdefs(view)
                set.add_all collect_redef_mpropdefs(view)
                return set
        end
+
+       # Collect intro abstract mmethodDef
+       fun collect_abstract_methods(view: ModelView): Set[MMethodDef] do
+               var set = new HashSet[MMethodDef]
+               var mpropdefs = collect_intro_mpropdefs(view)
+               for mpropdef in mpropdefs do
+                       if mpropdef isa MMethodDef then
+                               if mpropdef.is_abstract then set.add(mpropdef)
+                       end
+               end
+               return set
+       end
+
+       # Collect not defined properties
+       fun collect_not_define_properties(view: ModelView):Set[MMethodDef] do
+               var set = new HashSet[MMethodDef]
+               for mpropdef in collect_abstract_methods(view) do
+                       var redef_count = 0
+                       for mprop in mpropdef.mproperty.mpropdefs do
+                               if mprop.is_abstract then continue
+                               redef_count += 1
+                       end
+                       if redef_count == 0 then set.add(mpropdef)
+               end
+               return set
+       end
 end
index 7adbd49..3402abf 100644 (file)
@@ -17,9 +17,7 @@ module method_analyze_metrics
 
 # We usualy need specific phases
 # NOTE: `frontend` is sufficent in most case (it is often too much)
-import metrics_base
-import mclasses_metrics
-import semantize
+import nitsmell_toolcontext
 import mclassdef_collect
 
 
@@ -41,19 +39,18 @@ fun call_analyze_methods(mclassdef: MClassDef, model_builder: ModelBuilder): Arr
 end
 
 fun set_analyse_result_methoddef(mmethoddef: MMethodDef, visitor: MethodAnalyzeMetrics): MMethodDef do
-       mmethoddef.total_call = visitor.total_call
        mmethoddef.line_number = visitor.line_number.length
        mmethoddef.total_self_call = visitor.total_self_call
-       mmethoddef.total_extern_call = visitor.total_call - visitor.total_self_call
+       mmethoddef.class_call = visitor.class_call
        return mmethoddef
 end
 
 public class MethodAnalyzeMetrics
        super Visitor
        var ameth_prop_def: AMethPropdef
-       var total_call = 0
        var line_number = new Counter[nullable Int]
        var total_self_call = 0
+       var class_call = new Counter[MClassType]
 
        redef fun visit(n) do
                n.visit_all(self)
@@ -64,11 +61,11 @@ public class MethodAnalyzeMetrics
                                end
                        end
                end
-
                if n isa ASendExpr then
                        var callsite = n.callsite
                        if callsite != null then
-                               self.total_call += 1
+                               var class_site_recv = callsite.recv
+                               if class_site_recv isa MClassType then class_call.inc(class_site_recv)
                                if callsite.recv_is_self then self.total_self_call += 1
                        end
                end
@@ -76,8 +73,7 @@ public class MethodAnalyzeMetrics
 end
 
 redef class MMethodDef
-       var total_call = 0
        var line_number = 0
        var total_self_call = 0
-       var total_extern_call = 0
+       var class_call = new Counter[MClassType]
 end
diff --git a/src/metrics/nitsmell_toolcontext.nit b/src/metrics/nitsmell_toolcontext.nit
new file mode 100644 (file)
index 0000000..c0c3a7e
--- /dev/null
@@ -0,0 +1,103 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module nitsmell_toolcontext
+
+import modelbuilder
+import csv
+import counter
+import console
+
+redef class ToolContext
+
+       # --all
+       var opt_all = new OptionBool("Print all code smells for top 10 class", "--all")
+       # --get-all
+       var opt_get_all = new OptionBool("Print all code smells for all class", "--get-all")
+       # --feature-envy
+       var opt_feature_envy = new OptionBool("Print feature envy", "--feature-envy")
+       # --large-class
+       var opt_large_class = new OptionBool("Print large class", "--large-class")
+       # --long-methods
+       var opt_long_method = new OptionBool("Print long method", "--long-methods")
+       # --no-abstract-implementation
+       var opt_no_abstract_implementation = new OptionBool("Print the no implemented abstract method", "--no-abstract-implementation")
+       # --long-params
+       var opt_long_params = new OptionBool("Print long parameters", "--long-params")
+       # --move-generics
+       var opt_move_generics = new OptionBool("Print the move proposition for generic class", "--move-generics")
+       # --move-generics
+       var opt_long_method_threshold = new OptionInt("Select long method threshold", 0 ,"--long-method-threshold")
+       # --long-method-threshold
+       var opt_long_params_threshold = new OptionInt("Select long method parameters threshold", 0 ,"--long-params-threshold")
+       # --long-params-threshold
+       var opt_nocolors = new OptionBool("Disable colors in console outputs", "--no-colors")
+
+       redef init
+       do
+               super
+               self.option_context.add_option(opt_all)
+               self.option_context.add_option(opt_large_class)
+               self.option_context.add_option(opt_get_all)
+               self.option_context.add_option(opt_feature_envy)
+               self.option_context.add_option(opt_long_method)
+               self.option_context.add_option(opt_no_abstract_implementation)
+               self.option_context.add_option(opt_long_params)
+               self.option_context.add_option(opt_long_method_threshold)
+               self.option_context.add_option(opt_long_params_threshold)
+               self.option_context.add_option(opt_move_generics)
+               self.option_context.add_option(opt_nocolors)
+       end
+
+       # Format and colorize a string heading of level 1 for console output.
+       #
+       # Default style is yellow and bold.
+       fun format_h1(str: String): String do
+               if opt_nocolors.value then return str
+               return str.yellow.bold
+       end
+
+       # Format and colorize a string heading of level 2 for console output.
+       #
+       # Default style is white and bold.
+       fun format_h2(str: String): String do
+               if opt_nocolors.value then return str
+               return str.bold
+       end
+
+       # Format and colorize a string heading of level 3 for console output.
+       #
+       # Default style is white and nobold.
+       fun format_h3(str: String): String do
+               if opt_nocolors.value then return str
+               return str
+       end
+
+       # Format and colorize a string heading of level 4 for console output.
+       #
+       # Default style is green.
+       fun format_h4(str: String): String do
+               if opt_nocolors.value then return str
+               return str.green
+       end
+
+       # Format and colorize a string heading of level 5 for console output.
+       #
+       # Default style is light gray.
+       fun format_p(str: String): String do
+               if opt_nocolors.value then return str
+               return str.light_gray
+       end
+end
\ No newline at end of file
index da8454a..ea6a9be 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import metrics_base
-import mclasses_metrics
+import nitsmell_toolcontext
 import semantize
 
 import codesmells_metrics
+# For force nit to do the good linĂ©arisation to remove the toolcontext redef warning
+redef class ToolContext
+     redef init do super
+end
 
 # Create a tool context to handle options and paths
 var toolcontext = new ToolContext
index 1c18141..a8ff412 100644 (file)
@@ -58,4 +58,4 @@ class NoLargeclass
        var testVariable = 0
 
        fun test do end
-end
\ No newline at end of file
+end
index 584ef44..b9db6b5 100644 (file)
@@ -35,4 +35,11 @@ class LongMethodClass
                var starter = new Starter
                test_variable = 3
        end
-end
\ No newline at end of file
+
+       fun extra_long_method do
+               var starter = new Starter
+               test_variable = 3
+               test_variable = 5
+               test_variable = 8
+       end
+end
index 6988536..df05354 100644 (file)
@@ -20,7 +20,7 @@ import platform
 class Starter
        fun no_para do end
 
-       fun no_para2() do end
+       fun no_para2 do end
 end
 
 class Test
@@ -31,4 +31,8 @@ class Test
        fun long_list_parameter(numbers : Int, para1 : Bool, para2 : Float, para3 : Int, para4 : Starter) do
                var starter = new Starter
        end
+
+       fun extra_long_list_parameter(numbers : Int, para1 : Bool, para2 : Float, para3 : Int, para4 : Starter,para5 : Int, para6 : Int) do
+               var starter = new Starter
+       end
 end
diff --git a/tests/TestNitsmells/NoAbstractImplemented/longparameterlist.nit b/tests/TestNitsmells/NoAbstractImplemented/longparameterlist.nit
new file mode 100644 (file)
index 0000000..ac93348
--- /dev/null
@@ -0,0 +1,48 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A test program with a fake model to check model tools.
+module longparameterlist
+
+import platform
+
+class Starter
+       fun no_para do end
+
+       fun no_para2 do end
+
+       fun name: Int is abstract
+
+       fun name2: Int is abstract
+
+       var toto: Int is abstract
+end
+
+class NoImplemented
+       super Starter
+
+       fun short_list_parameter(numbers : Int, para1 : Bool, para2 : Float, para3 : Int) do
+               var starter = new Starter
+       end
+
+       fun long_list_parameter(numbers : Int, para1 : Bool, para2 : Float, para3 : Int, para4 : Starter) do
+               var starter = new Starter
+       end
+end
+
+class Implemented
+       super NoImplemented
+
+       redef fun name do return 1 end
+end
index 0032cd9..0b5e85d 100644 (file)
@@ -1,5 +1,8 @@
---no-colors test_prog/
---no-colors TestNitsmells/FeatureEnvy/
---no-colors TestNitsmells/LargeClass/
---no-colors TestNitsmells/LongMethod/
---no-colors TestNitsmells/LongParameterList/
\ No newline at end of file
+--no-colors --all test_prog/
+--no-colors --feature-envy TestNitsmells/FeatureEnvy/
+--no-colors --large-class TestNitsmells/LargeClass/
+--no-colors --long-methods TestNitsmells/LongMethod/
+--no-colors --long-params TestNitsmells/LongParameterList/
+--no-colors --no-abstract-implementation TestNitsmells/NoAbstractImplemented/
+--no-colors --long-methods --long-method-threshold 3 TestNitsmells/LongMethod/
+--no-colors --long-params --long-params-threshold 5 TestNitsmells/LongParameterList/
index 68b3680..439a213 100644 (file)
@@ -1,20 +1,10 @@
 *** CODE SMELLS METRICS ***
 --- Code Smells Metrics ---
------------
-test_prog$Character
-Large class: 6 attributes and 18 methods (5.414A 7.161M Average)
-Feature envy:
-       Affected method(s):
-               -total_strengh 4/9
-               -total_endurance 4/9
-               -total_intelligence 4/9
+--------------------
+Full name: test_prog$Character Location: test_prog/rpg/character.nit:21,1--68,3
 Long method:  Average 1 lines
        Affected method(s):
                -total_strengh has 2 lines
                -total_endurance has 2 lines
                -total_intelligence has 2 lines
------------
-test_prog::combat$Dwarf
-Feature envy:
-       Affected method(s):
-               -dps 1/3
+Large class: 6 attributes and 18 methods (5.414A 7.161M Average)
index 26092c7..39c9a4b 100644 (file)
@@ -1,7 +1,7 @@
 *** CODE SMELLS METRICS ***
 --- Code Smells Metrics ---
------------
-TestNitsmells$FeatureEnvy
+--------------------
+Full name: TestNitsmells$FeatureEnvy Location: TestNitsmells/FeatureEnvy/featureenvy.nit:32,1--42,3
 Feature envy:
        Affected method(s):
-               -feature_envy_method 2/6
+               -feature_envy_method() 2/3 move to Starter
index fd60962..0ef08f3 100644 (file)
@@ -1,5 +1,5 @@
 *** CODE SMELLS METRICS ***
 --- Code Smells Metrics ---
------------
-TestNitsmells$LargeClass
+--------------------
+Full name: TestNitsmells$LargeClass Location: TestNitsmells/LargeClass/largeclass.nit:20,1--55,3
 Large class: 18 attributes and 48 methods (17.515A 30.464M Average)
index 1fe9b09..6f057c0 100644 (file)
@@ -1,7 +1,7 @@
 *** CODE SMELLS METRICS ***
 --- Code Smells Metrics ---
------------
-TestNitsmells$LongMethodClass
-Long method:  Average 1 lines
+--------------------
+Full name: TestNitsmells$LongMethodClass Location: TestNitsmells/LongMethod/longmethod.nit:31,1--45,3
+Long method:  Average 3 lines
        Affected method(s):
-               -long_method has 2 lines
+               -extra_long_method has 4 lines
diff --git a/tests/sav/nitsmells_args5.res b/tests/sav/nitsmells_args5.res
new file mode 100644 (file)
index 0000000..82ee73d
--- /dev/null
@@ -0,0 +1,8 @@
+*** CODE SMELLS METRICS ***
+--- Code Smells Metrics ---
+--------------------
+Full name: TestNitsmells$Test Location: TestNitsmells/LongParameterList/longparameterlist.nit:26,1--38,3
+Long parameter list:
+       Affected method(s):
+               -long_list_parameter has 5 parameters
+               -extra_long_list_parameter has 7 parameters
diff --git a/tests/sav/nitsmells_args6.res b/tests/sav/nitsmells_args6.res
new file mode 100644 (file)
index 0000000..abf171b
--- /dev/null
@@ -0,0 +1,9 @@
+*** CODE SMELLS METRICS ***
+--- Code Smells Metrics ---
+--------------------
+Full name: TestNitsmells$Starter Location: TestNitsmells/NoAbstractImplemented/longparameterlist.nit:20,1--30,3
+No Implemented abstract property:
+       Affected method(s):
+               -name2
+               -toto
+               -toto=
diff --git a/tests/sav/nitsmells_args7.res b/tests/sav/nitsmells_args7.res
new file mode 100644 (file)
index 0000000..6f057c0
--- /dev/null
@@ -0,0 +1,7 @@
+*** CODE SMELLS METRICS ***
+--- Code Smells Metrics ---
+--------------------
+Full name: TestNitsmells$LongMethodClass Location: TestNitsmells/LongMethod/longmethod.nit:31,1--45,3
+Long method:  Average 3 lines
+       Affected method(s):
+               -extra_long_method has 4 lines
diff --git a/tests/sav/nitsmells_args8.res b/tests/sav/nitsmells_args8.res
new file mode 100644 (file)
index 0000000..b03d0fa
--- /dev/null
@@ -0,0 +1,7 @@
+*** CODE SMELLS METRICS ***
+--- Code Smells Metrics ---
+--------------------
+Full name: TestNitsmells$Test Location: TestNitsmells/LongParameterList/longparameterlist.nit:26,1--38,3
+Long parameter list:
+       Affected method(s):
+               -extra_long_list_parameter has 7 parameters