Skip to content

Commit

Permalink
feat(spoon): Add FinalStaticMethod analyzer (#845)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinWitt authored Jul 15, 2023
1 parent c10c310 commit c4ea0e8
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.github.martinwitt.spoon_analyzer.badsmells.access_static_via_instance.AccessStaticViaInstance;
import io.github.martinwitt.spoon_analyzer.badsmells.array_can_be_replaced_with_enum_values.ArrayCanBeReplacedWithEnumValues;
import io.github.martinwitt.spoon_analyzer.badsmells.charset_object_can_be_used.CharsetObjectCanBeUsed;
import io.github.martinwitt.spoon_analyzer.badsmells.final_static_method.FinalStaticMethod;
import io.github.martinwitt.spoon_analyzer.badsmells.innerclass_may_be_static.InnerClassMayBeStatic;
import io.github.martinwitt.spoon_analyzer.badsmells.non_protected_constructor_In_abstract_class.NonProtectedConstructorInAbstractClass;
import io.github.martinwitt.spoon_analyzer.badsmells.private_final_method.PrivateFinalMethod;
Expand Down Expand Up @@ -138,4 +139,10 @@ public AnalyzerResult visit(UnnecessaryTostring badSmell) {
badSmell.getNotNeededTostring().getOriginalSourceFragment().toString();
return toSpoonAnalyzerResult(badSmell, badSmell.getNotNeededTostring().getPosition(), snippet);
}

@Override
public AnalyzerResult visit(FinalStaticMethod badSmell) {
String snippet = badSmell.getMethod().getSignature();
return toSpoonAnalyzerResult(badSmell, badSmell.getMethod().getPosition(), snippet);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ public static Matcher<CtModifiable> isFinal() {
return v -> v.getModifiers().contains(ModifierKind.FINAL);
}

/**
* Returns a matcher that matches elements that are static.
*
* @return a matcher that matches elements that are static
*/
public static Matcher<CtModifiable> isStatic() {
return v -> v.isStatic();
}

/**
* Returns a matcher that matches elements that match all of the given matchers.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.github.martinwitt.spoon_analyzer.badsmells.access_static_via_instance.AccessStaticViaInstance;
import io.github.martinwitt.spoon_analyzer.badsmells.array_can_be_replaced_with_enum_values.ArrayCanBeReplacedWithEnumValues;
import io.github.martinwitt.spoon_analyzer.badsmells.charset_object_can_be_used.CharsetObjectCanBeUsed;
import io.github.martinwitt.spoon_analyzer.badsmells.final_static_method.FinalStaticMethod;
import io.github.martinwitt.spoon_analyzer.badsmells.innerclass_may_be_static.InnerClassMayBeStatic;
import io.github.martinwitt.spoon_analyzer.badsmells.non_protected_constructor_In_abstract_class.NonProtectedConstructorInAbstractClass;
import io.github.martinwitt.spoon_analyzer.badsmells.private_final_method.PrivateFinalMethod;
Expand Down Expand Up @@ -67,6 +68,10 @@ default U visit(UnnecessaryTostring badSmell) {
return emptyResult();
}

default U visit(FinalStaticMethod badSmell) {
return emptyResult();
}

default U emptyResult() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.martinwitt.spoon_analyzer.badsmells.access_static_via_instance.AccessStaticViaInstanceAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.array_can_be_replaced_with_enum_values.ArrayCanBeReplacedWithEnumValuesAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.charset_object_can_be_used.CharsetObjectCanBeUsedAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.final_static_method.FinalStaticMethodAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.innerclass_may_be_static.InnerClassMayBeStaticAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.non_protected_constructor_In_abstract_class.NonProtectedConstructorInAbstractClassAnalyzer;
import io.github.martinwitt.spoon_analyzer.badsmells.private_final_method.PrivateFinalMethodAnalyzer;
Expand All @@ -28,6 +29,7 @@ public SpoonAnalyzer() {
localAnalyzers.add(new AccessStaticViaInstanceAnalyzer());
localAnalyzers.add(new ArrayCanBeReplacedWithEnumValuesAnalyzer());
localAnalyzers.add(new CharsetObjectCanBeUsedAnalyzer());
localAnalyzers.add(new FinalStaticMethodAnalyzer());
localAnalyzers.add(new IndexOfReplaceableByContainsAnalyzer());
localAnalyzers.add(new InnerClassMayBeStaticAnalyzer());
localAnalyzers.add(new NonProtectedConstructorInAbstractClassAnalyzer());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.github.martinwitt.spoon_analyzer.badsmells.final_static_method;

import io.github.martinwitt.spoon_analyzer.BadSmell;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;

public class FinalStaticMethod implements BadSmell {

private static final String NAME = "FinalStaticMethod";
private static final String description =
"A final method is a method that cannot be overridden in a subclass. As static methods are bound to the class the cant be overridden only hidden.";
private final CtMethod<?> method;
private final CtType<?> affectedType;

public FinalStaticMethod(CtMethod<?> method, CtType<?> affectedType) {
this.method = method;
this.affectedType = affectedType;
}

@Override
public String getName() {
return NAME;
}

@Override
public String getDescription() {
return description;
}

@Override
public CtType<?> getAffectedType() {
return affectedType;
}

/**
* @return the final static method
*/
public CtMethod<?> getMethod() {
return method;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.martinwitt.spoon_analyzer.badsmells.final_static_method;

import io.github.martinwitt.laughing_train.spoonutils.matcher.Matchers;
import io.github.martinwitt.spoon_analyzer.BadSmell;
import io.github.martinwitt.spoon_analyzer.LocalAnalyzer;
import java.util.ArrayList;
import java.util.List;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.Filter;

public class FinalStaticMethodAnalyzer implements LocalAnalyzer {

@Override
public List<BadSmell> analyze(CtType<?> clazz) {
List<BadSmell> badSmells = new ArrayList<>();
List<CtMethod<?>> elements = clazz.getElements(new FinalStaticMethodFilter());
for (CtMethod<?> method : elements) {
badSmells.add(new FinalStaticMethod(method, clazz));
}
return badSmells;
}

/**
* A filter that matches final static methods.
*/
private static class FinalStaticMethodFilter implements Filter<CtMethod<?>> {

@Override
public boolean matches(CtMethod<?> element) {
return Matchers.allOf(Matchers.isFinal(), (Matchers.isStatic())).matches(element);
}
}
}

0 comments on commit c4ea0e8

Please sign in to comment.