From 4e4957d3b9f57995106dd63c99fdca474db5cdd9 Mon Sep 17 00:00:00 2001 From: Florian Deljarry Date: Fri, 23 Jun 2017 11:17:24 -0400 Subject: [PATCH] Nitsmell : Adding new code smells and print console updated 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 --- src/metrics/codesmells_metrics.nit | 200 +++++++++++++++----- src/metrics/mclassdef_collect.nit | 38 +++- src/metrics/method_analyze_metrics.nit | 16 +- src/metrics/nitsmell_toolcontext.nit | 103 ++++++++++ src/nitsmells.nit | 7 +- tests/TestNitsmells/LargeClass/largeclass.nit | 2 +- tests/TestNitsmells/LongMethod/longmethod.nit | 9 +- .../LongParameterList/longparameterlist.nit | 6 +- .../NoAbstractImplemented/longparameterlist.nit | 48 +++++ tests/nitsmells.args | 13 +- tests/sav/nitsmells_args1.res | 16 +- tests/sav/nitsmells_args2.res | 6 +- tests/sav/nitsmells_args3.res | 4 +- tests/sav/nitsmells_args4.res | 8 +- tests/sav/nitsmells_args5.res | 8 + tests/sav/nitsmells_args6.res | 9 + tests/sav/nitsmells_args7.res | 7 + tests/sav/nitsmells_args8.res | 7 + 18 files changed, 412 insertions(+), 95 deletions(-) create mode 100644 src/metrics/nitsmell_toolcontext.nit create mode 100644 tests/TestNitsmells/NoAbstractImplemented/longparameterlist.nit create mode 100644 tests/sav/nitsmells_args5.res create mode 100644 tests/sav/nitsmells_args6.res create mode 100644 tests/sav/nitsmells_args7.res create mode 100644 tests/sav/nitsmells_args8.res diff --git a/src/metrics/codesmells_metrics.nit b/src/metrics/codesmells_metrics.nit index d09e769..e335d8f 100644 --- a/src/metrics/codesmells_metrics.nit +++ b/src/metrics/codesmells_metrics.nit @@ -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 diff --git a/src/metrics/mclassdef_collect.nit b/src/metrics/mclassdef_collect.nit index 5b6c937..84537ce 100644 --- a/src/metrics/mclassdef_collect.nit +++ b/src/metrics/mclassdef_collect.nit @@ -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 diff --git a/src/metrics/method_analyze_metrics.nit b/src/metrics/method_analyze_metrics.nit index 7adbd49..3402abf 100644 --- a/src/metrics/method_analyze_metrics.nit +++ b/src/metrics/method_analyze_metrics.nit @@ -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 index 0000000..c0c3a7e --- /dev/null +++ b/src/metrics/nitsmell_toolcontext.nit @@ -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 diff --git a/src/nitsmells.nit b/src/nitsmells.nit index da8454a..ea6a9be 100644 --- a/src/nitsmells.nit +++ b/src/nitsmells.nit @@ -12,11 +12,14 @@ # 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 diff --git a/tests/TestNitsmells/LargeClass/largeclass.nit b/tests/TestNitsmells/LargeClass/largeclass.nit index 1c18141..a8ff412 100644 --- a/tests/TestNitsmells/LargeClass/largeclass.nit +++ b/tests/TestNitsmells/LargeClass/largeclass.nit @@ -58,4 +58,4 @@ class NoLargeclass var testVariable = 0 fun test do end -end \ No newline at end of file +end diff --git a/tests/TestNitsmells/LongMethod/longmethod.nit b/tests/TestNitsmells/LongMethod/longmethod.nit index 584ef44..b9db6b5 100644 --- a/tests/TestNitsmells/LongMethod/longmethod.nit +++ b/tests/TestNitsmells/LongMethod/longmethod.nit @@ -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 diff --git a/tests/TestNitsmells/LongParameterList/longparameterlist.nit b/tests/TestNitsmells/LongParameterList/longparameterlist.nit index 6988536..df05354 100644 --- a/tests/TestNitsmells/LongParameterList/longparameterlist.nit +++ b/tests/TestNitsmells/LongParameterList/longparameterlist.nit @@ -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 index 0000000..ac93348 --- /dev/null +++ b/tests/TestNitsmells/NoAbstractImplemented/longparameterlist.nit @@ -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 diff --git a/tests/nitsmells.args b/tests/nitsmells.args index 0032cd9..0b5e85d 100644 --- a/tests/nitsmells.args +++ b/tests/nitsmells.args @@ -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/ diff --git a/tests/sav/nitsmells_args1.res b/tests/sav/nitsmells_args1.res index 68b3680..439a213 100644 --- a/tests/sav/nitsmells_args1.res +++ b/tests/sav/nitsmells_args1.res @@ -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) diff --git a/tests/sav/nitsmells_args2.res b/tests/sav/nitsmells_args2.res index 26092c7..39c9a4b 100644 --- a/tests/sav/nitsmells_args2.res +++ b/tests/sav/nitsmells_args2.res @@ -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 diff --git a/tests/sav/nitsmells_args3.res b/tests/sav/nitsmells_args3.res index fd60962..0ef08f3 100644 --- a/tests/sav/nitsmells_args3.res +++ b/tests/sav/nitsmells_args3.res @@ -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) diff --git a/tests/sav/nitsmells_args4.res b/tests/sav/nitsmells_args4.res index 1fe9b09..6f057c0 100644 --- a/tests/sav/nitsmells_args4.res +++ b/tests/sav/nitsmells_args4.res @@ -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 index 0000000..82ee73d --- /dev/null +++ b/tests/sav/nitsmells_args5.res @@ -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 index 0000000..abf171b --- /dev/null +++ b/tests/sav/nitsmells_args6.res @@ -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 index 0000000..6f057c0 --- /dev/null +++ b/tests/sav/nitsmells_args7.res @@ -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 index 0000000..b03d0fa --- /dev/null +++ b/tests/sav/nitsmells_args8.res @@ -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 -- 1.7.9.5