From 5357c794225f57cb13a07c3d56887901688a36f0 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Sun, 3 Sep 2023 20:47:03 +0200 Subject: [PATCH] =?UTF-8?q?feat(spoon):=20=E2=9C=A8=20Provide=20a=20unifie?= =?UTF-8?q?d=20api=20for=20refactoring=20a=20repository=20with=20code=20tr?= =?UTF-8?q?ansformations=20api=20(#1011)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rules => }/AbstractRefactoring.java | 2 +- .../analyzer/qodana/QodanaRefactor.java | 2 +- .../analyzer/qodana/QodanaRules.java | 2 +- .../analyzer/qodana/rules/CodeBlock2Expr.java | 1 + .../qodana/rules/InnerClassMayBeStatic.java | 1 + .../qodana/rules/MethodMayBeStatic.java | 1 + ...onProtectedConstructorInAbstractClass.java | 1 + .../NonStrictComparisonCanBeEquality.java | 1 + ...terNameDiffersFromOverriddenParameter.java | 1 + .../rules/PointlessBooleanExpression.java | 1 + .../rules/ProtectedMemberInFinalClass.java | 1 + .../qodana/rules/RedundantArrayCreation.java | 1 + .../rules/SizeReplaceableByIsEmpty.java | 1 + ...oArrayCallWithZeroLengthArrayArgument.java | 1 + .../rules/UnnecessaryInterfaceModifier.java | 1 + .../rules/UnnecessaryLocalVariable.java | 1 + .../qodana/rules/UnnecessaryModifier.java | 1 + .../qodana/rules/UnnecessaryReturn.java | 1 + .../qodana/rules/UnnecessaryStringEscape.java | 1 + .../qodana/rules/UnnecessaryToStringCall.java | 1 + .../analyzer/qodana/rules/UnusedImport.java | 1 + .../analyzer/qodana/rules/UnusedLabel.java | 1 + ...UtilityClassWithoutPrivateConstructor.java | 1 + .../analyzer/spoon/SpoonRefactor.java | 39 +++++++++++++++ .../analyzer/spoon/SpoonRules.java | 38 ++++++++++++++ .../code_solver/api/CodeRefactoring.java | 50 +++++++++++++++++++ .../keksdose/spoon/code_solver/DocGen.java | 2 +- .../TransformationTestUtils.java | 2 +- .../martinwitt/laughing_train/github/App.java | 45 ----------------- .../services/RefactorService.java | 23 ++------- 30 files changed, 157 insertions(+), 68 deletions(-) rename code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/{qodana/rules => }/AbstractRefactoring.java (97%) create mode 100644 code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRefactor.java create mode 100644 code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRules.java create mode 100644 code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/api/CodeRefactoring.java diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/AbstractRefactoring.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/AbstractRefactoring.java similarity index 97% rename from code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/AbstractRefactoring.java rename to code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/AbstractRefactoring.java index 0537959d8..98bd569d4 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/AbstractRefactoring.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/AbstractRefactoring.java @@ -1,4 +1,4 @@ -package xyz.keksdose.spoon.code_solver.analyzer.qodana.rules; +package xyz.keksdose.spoon.code_solver.analyzer; import io.github.martinwitt.laughing_train.domain.entity.AnalyzerResult; import java.nio.file.Path; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRefactor.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRefactor.java index f2720608a..cb743c632 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRefactor.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRefactor.java @@ -11,7 +11,7 @@ import java.util.function.Consumer; import java.util.function.Function; import spoon.reflect.declaration.CtType; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.AbstractRefactoring; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.MethodMayBeStatic; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.NonProtectedConstructorInAbstractClass; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.NonStrictComparisonCanBeEquality; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRules.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRules.java index 97483a42a..e78e24c61 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRules.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/QodanaRules.java @@ -4,8 +4,8 @@ import io.github.martinwitt.laughing_train.domain.value.RuleId; import java.util.List; import java.util.function.Function; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.AnalyzerRule; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.CodeBlock2Expr; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.InnerClassMayBeStatic; import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.MethodMayBeStatic; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/CodeBlock2Expr.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/CodeBlock2Expr.java index 884bed769..6ea973fd5 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/CodeBlock2Expr.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/CodeBlock2Expr.java @@ -8,6 +8,7 @@ import spoon.reflect.code.CtLambda; import spoon.reflect.code.CtReturn; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/InnerClassMayBeStatic.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/InnerClassMayBeStatic.java index a8e00efb8..315ca3c8d 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/InnerClassMayBeStatic.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/InnerClassMayBeStatic.java @@ -7,6 +7,7 @@ import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.ModifierKind; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/MethodMayBeStatic.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/MethodMayBeStatic.java index 599404ee0..7812e86fe 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/MethodMayBeStatic.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/MethodMayBeStatic.java @@ -15,6 +15,7 @@ import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.reflect.CtExtendedModifier; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonProtectedConstructorInAbstractClass.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonProtectedConstructorInAbstractClass.java index ba4504a69..7f2537e13 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonProtectedConstructorInAbstractClass.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonProtectedConstructorInAbstractClass.java @@ -13,6 +13,7 @@ import spoon.reflect.declaration.ModifierKind; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.reflect.CtExtendedModifier; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonStrictComparisonCanBeEquality.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonStrictComparisonCanBeEquality.java index 451e5be29..56b185679 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonStrictComparisonCanBeEquality.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/NonStrictComparisonCanBeEquality.java @@ -7,6 +7,7 @@ import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ParameterNameDiffersFromOverriddenParameter.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ParameterNameDiffersFromOverriddenParameter.java index 0d6fae529..650a20cd8 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ParameterNameDiffersFromOverriddenParameter.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ParameterNameDiffersFromOverriddenParameter.java @@ -10,6 +10,7 @@ import spoon.reflect.declaration.CtType; import spoon.reflect.reference.CtParameterReference; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/PointlessBooleanExpression.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/PointlessBooleanExpression.java index d94839ece..82a495bb8 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/PointlessBooleanExpression.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/PointlessBooleanExpression.java @@ -8,6 +8,7 @@ import spoon.reflect.code.CtExpression; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ProtectedMemberInFinalClass.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ProtectedMemberInFinalClass.java index faaf8af78..c7e3a703a 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ProtectedMemberInFinalClass.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ProtectedMemberInFinalClass.java @@ -11,6 +11,7 @@ import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeMember; import spoon.reflect.declaration.ModifierKind; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/RedundantArrayCreation.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/RedundantArrayCreation.java index 837c1d0b0..3346bc250 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/RedundantArrayCreation.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/RedundantArrayCreation.java @@ -5,6 +5,7 @@ import java.util.List; import spoon.reflect.code.CtNewArray; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/SizeReplaceableByIsEmpty.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/SizeReplaceableByIsEmpty.java index db2157ce5..6394a588c 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/SizeReplaceableByIsEmpty.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/SizeReplaceableByIsEmpty.java @@ -13,6 +13,7 @@ import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ToArrayCallWithZeroLengthArrayArgument.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ToArrayCallWithZeroLengthArrayArgument.java index 30846883c..bcb32884d 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ToArrayCallWithZeroLengthArrayArgument.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/ToArrayCallWithZeroLengthArrayArgument.java @@ -7,6 +7,7 @@ import spoon.reflect.code.CtNewArray; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryInterfaceModifier.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryInterfaceModifier.java index d0b99dd60..a5d27758b 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryInterfaceModifier.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryInterfaceModifier.java @@ -10,6 +10,7 @@ import spoon.reflect.declaration.CtTypeMember; import spoon.reflect.declaration.ModifierKind; import spoon.support.reflect.CtExtendedModifier; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryLocalVariable.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryLocalVariable.java index f54359abc..24aebd68d 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryLocalVariable.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryLocalVariable.java @@ -12,6 +12,7 @@ import spoon.reflect.code.CtVariableRead; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryModifier.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryModifier.java index 76d98db6e..af6e39967 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryModifier.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryModifier.java @@ -7,6 +7,7 @@ import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtModifiable; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryReturn.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryReturn.java index 07b182b20..463db921b 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryReturn.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryReturn.java @@ -6,6 +6,7 @@ import spoon.reflect.code.CtReturn; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryStringEscape.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryStringEscape.java index b281ba8b9..351342b06 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryStringEscape.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryStringEscape.java @@ -6,6 +6,7 @@ import spoon.reflect.code.CtLiteral; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryToStringCall.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryToStringCall.java index 681caca36..11333c63c 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryToStringCall.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnnecessaryToStringCall.java @@ -9,6 +9,7 @@ import spoon.reflect.code.CtInvocation; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.diffs.DiffCleanModes; import xyz.keksdose.spoon.code_solver.history.Change; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedImport.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedImport.java index f0076ac8b..03a86768f 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedImport.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedImport.java @@ -6,6 +6,7 @@ import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtType; import spoon.support.util.ModelList; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedLabel.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedLabel.java index 0d2b6ac70..53981b494 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedLabel.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UnusedLabel.java @@ -7,6 +7,7 @@ import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.analyzer.PositionScanner; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UtilityClassWithoutPrivateConstructor.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UtilityClassWithoutPrivateConstructor.java index c768fd6dd..4910a2590 100644 --- a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UtilityClassWithoutPrivateConstructor.java +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/qodana/rules/UtilityClassWithoutPrivateConstructor.java @@ -15,6 +15,7 @@ import spoon.reflect.declaration.ModifierKind; import spoon.reflect.factory.Factory; import spoon.reflect.visitor.filter.TypeFilter; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.Change; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.MarkdownString; diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRefactor.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRefactor.java new file mode 100644 index 000000000..2806c5eca --- /dev/null +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRefactor.java @@ -0,0 +1,39 @@ +package xyz.keksdose.spoon.code_solver.analyzer.spoon; + +import io.github.martinwitt.laughing_train.domain.entity.AnalyzerResult; +import io.github.martinwitt.laughing_train.domain.value.RuleId; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import spoon.reflect.declaration.CtType; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; +import xyz.keksdose.spoon.code_solver.history.ChangeListener; +import xyz.keksdose.spoon.code_solver.transformations.TransformationProcessor; + +/** + * Entry point for spoon based refactoring. This class is used to apply all refactors which are reported by spoon. + */ +public class SpoonRefactor extends TransformationProcessor> { + + private Map> ruleParser; + private List refactors; + + public SpoonRefactor(ChangeListener changeListener, List badSmells) { + super(changeListener); + ruleParser = new HashMap<>(); + Arrays.stream(SpoonRules.values()).forEach(rule -> ruleParser.put(rule.getRuleId(), rule.getRefactoring())); + for (AnalyzerResult result : badSmells) { + Optional.ofNullable(ruleParser.get(result.ruleID())).ifPresent(v -> refactors.add(v.apply(result))); + } + } + + @Override + public void process(CtType element) { + for (AbstractRefactoring refactoring : refactors) { + refactoring.refactor(listener, element); + } + } +} diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRules.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRules.java new file mode 100644 index 000000000..384cbd4bb --- /dev/null +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/analyzer/spoon/SpoonRules.java @@ -0,0 +1,38 @@ +package xyz.keksdose.spoon.code_solver.analyzer.spoon; + +import io.github.martinwitt.laughing_train.domain.entity.AnalyzerResult; +import io.github.martinwitt.laughing_train.domain.value.RuleId; +import java.util.List; +import java.util.function.Function; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; +import xyz.keksdose.spoon.code_solver.analyzer.AnalyzerRule; +import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.MethodMayBeStatic; +import xyz.keksdose.spoon.code_solver.transformations.BadSmell; + +/** + * Enum for all spoon based rules. + */ +public enum SpoonRules implements AnalyzerRule { + METHOD_MAY_BE_STATIC("MethodMayBeStatic", MethodMayBeStatic::new); + + private final RuleId ruleId; + private final Function refactoring; + + SpoonRules(String ruleId, Function refactoring) { + this.ruleId = new RuleId(ruleId); + this.refactoring = refactoring; + } + + @Override + public RuleId getRuleId() { + return ruleId; + } + + Function getRefactoring() { + return refactoring; + } + + List getDescription() { + return getRefactoring().apply(null).getHandledBadSmells(); + } +} diff --git a/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/api/CodeRefactoring.java b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/api/CodeRefactoring.java new file mode 100644 index 000000000..86d033fb3 --- /dev/null +++ b/code-transformation/src/main/java/xyz/keksdose/spoon/code_solver/api/CodeRefactoring.java @@ -0,0 +1,50 @@ +package xyz.keksdose.spoon.code_solver.api; + +import com.google.common.flogger.FluentLogger; +import io.github.martinwitt.laughing_train.domain.entity.AnalyzerResult; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; +import xyz.keksdose.spoon.code_solver.TransformationEngine; +import xyz.keksdose.spoon.code_solver.analyzer.qodana.QodanaRefactor; +import xyz.keksdose.spoon.code_solver.analyzer.qodana.QodanaRules; +import xyz.keksdose.spoon.code_solver.analyzer.spoon.SpoonRefactor; +import xyz.keksdose.spoon.code_solver.diffs.DiffCleaner; +import xyz.keksdose.spoon.code_solver.history.ChangeListener; +import xyz.keksdose.spoon.code_solver.history.Changelog; +import xyz.keksdose.spoon.code_solver.transformations.TransformationProcessor; + +/** + * This class is the entry point for the code transformation. It takes a repository and a list of badsmells. It then applies the transformations to the repository and returns a changelog. + */ +public class CodeRefactoring { + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private final List, TransformationProcessor>> + refactor = new ArrayList<>(); + + public CodeRefactoring() { + refactor.add((u, v) -> new QodanaRefactor(EnumSet.allOf(QodanaRules.class), u, v)); + refactor.add((u, v) -> new SpoonRefactor(u, v)); + } + + public Changelog refactorBadSmells(Path repository, List results) { + ChangeListener listener = new ChangeListener(); + logger.atInfo().log("Refactoring %s", repository); + DiffCleaner diffCleaner = new DiffCleaner(); + List>> function = new ArrayList<>(); + for (BiFunction, TransformationProcessor> refactorSupplier : + refactor) { + function.add(v -> refactorSupplier.apply(v, results)); + } + TransformationEngine transformationEngine = new TransformationEngine(function); + transformationEngine.setChangeListener(listener); + Changelog log = transformationEngine.applyToGivenPath(repository.toString()); + log.getChanges().forEach(change -> diffCleaner.clean(repository, change)); + return log; + } +} diff --git a/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/DocGen.java b/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/DocGen.java index e6fb9ab47..a1ab4c1da 100644 --- a/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/DocGen.java +++ b/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/DocGen.java @@ -13,7 +13,7 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.visitor.filter.TypeFilter; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.AbstractRefactoring; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.transformations.BadSmell; import xyz.keksdose.spoon.code_solver.transformations.TransformationProcessor; diff --git a/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/transformations/TransformationTestUtils.java b/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/transformations/TransformationTestUtils.java index 770e8bff9..56f08ec5a 100644 --- a/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/transformations/TransformationTestUtils.java +++ b/code-transformation/src/test/java/xyz/keksdose/spoon/code_solver/transformations/TransformationTestUtils.java @@ -11,7 +11,7 @@ import spoon.reflect.declaration.CtType; import xyz.keksdose.spoon.code_solver.TestHelper; import xyz.keksdose.spoon.code_solver.TransformationEngine; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.rules.AbstractRefactoring; +import xyz.keksdose.spoon.code_solver.analyzer.AbstractRefactoring; import xyz.keksdose.spoon.code_solver.history.ChangeListener; /** diff --git a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java b/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java index 4442de613..61e8f0e09 100644 --- a/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java +++ b/github-bot/src/main/java/io/github/martinwitt/laughing_train/github/App.java @@ -14,7 +14,6 @@ import io.github.martinwitt.laughing_train.services.QodanaService; import io.quarkiverse.githubapp.event.Issue; import jakarta.inject.Inject; -import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; @@ -23,19 +22,13 @@ import java.util.Date; import java.util.List; import java.util.Map; -import java.util.function.Function; import java.util.stream.Collectors; -import org.apache.commons.io.FileUtils; import org.kohsuke.github.GHEventPayload; import org.kohsuke.github.GHIssue; import org.kohsuke.github.GHRef; import org.kohsuke.github.GHRepository; import spoon.reflect.declaration.CtType; -import xyz.keksdose.spoon.code_solver.TransformationEngine; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.QodanaRefactor; import xyz.keksdose.spoon.code_solver.history.Change; -import xyz.keksdose.spoon.code_solver.history.ChangeListener; -import xyz.keksdose.spoon.code_solver.transformations.TransformationProcessor; public class App { @@ -78,11 +71,6 @@ void onConfigEdit(@Issue.Edited GHEventPayload.Issue issueComment) throws IOExce issueComment.getIssue().setBody(config.regenerateConfig()); } refreshConfig(issueComment); - if (containsFlag(issueComment.getIssue(), CREATE_FIXES_BUTTON)) { - issueComment.getIssue().setBody(refreshFlag(issueComment.getIssue().getBody(), CREATE_FIXES_BUTTON)); - createFixes(issueComment); - logger.atInfo().log("Fixes created"); - } if (containsFlag(issueComment.getIssue(), DISABLE_ALL_RULES_BUTTON)) { issueComment.getIssue().setBody(refreshFlag(issueComment.getIssue().getBody(), DISABLE_ALL_RULES_BUTTON)); disableAllRules(); @@ -90,22 +78,6 @@ void onConfigEdit(@Issue.Edited GHEventPayload.Issue issueComment) throws IOExce } } - private void createFixes(GHEventPayload.Issue issueComment) throws IOException { - Path dir = Files.createTempDirectory(Constants.TEMP_FOLDER_PREFIX); - try (Closeable closeable = () -> FileUtils.deleteDirectory(dir.toFile())) { - List changes = refactorRepo(issueComment.getRepository().getHttpTransportUrl(), dir) - .getChangelog() - .getChanges(); - GHRepository repo = issueComment.getRepository(); - GitHubUtils.createLabelIfMissing(repo); - if (config.isGroupyByType()) { - createPullRequestForAffectedType(repo, dir, groupChangesByType(changes)); - } else { - createSinglePullRequest(repo, dir, changes); - } - } - } - private void refreshConfig(GHEventPayload.Issue issueComment) throws JsonProcessingException { String body = issueComment.getIssue().getBody(); @Var @@ -169,23 +141,6 @@ private void createSinglePullRequest(GHRepository repo, Path dir, List> function = - (v -> new QodanaRefactor(config.getActiveRules(), v, results)); - TransformationEngine transformationEngine = new TransformationEngine(List.of(function)); - transformationEngine.setChangeListener(changeListener); - System.out.println("refactorRepo: " + dir + "/" + config.getSrcFolder()); - transformationEngine.applyToGivenPath(dir + "/" + config.getSrcFolder()); - } catch (Exception e) { - logger.atSevere().withCause(e).log("Failed to refactor repo"); - } - return changeListener; - } - private Map, List> groupChangesByType(List changes) { return changes.stream().collect(Collectors.groupingBy(Change::getAffectedType)); } diff --git a/github-bot/src/main/java/io/github/martinwitt/laughing_train/services/RefactorService.java b/github-bot/src/main/java/io/github/martinwitt/laughing_train/services/RefactorService.java index b9f5e3d9c..358b43e78 100644 --- a/github-bot/src/main/java/io/github/martinwitt/laughing_train/services/RefactorService.java +++ b/github-bot/src/main/java/io/github/martinwitt/laughing_train/services/RefactorService.java @@ -25,9 +25,7 @@ import java.time.Instant; import java.util.Collection; import java.util.Date; -import java.util.EnumSet; import java.util.List; -import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.eclipse.microprofile.health.HealthCheckResponse; @@ -36,14 +34,10 @@ import org.kohsuke.github.GHRepository; import org.kohsuke.github.GitHub; import spoon.reflect.declaration.CtType; -import xyz.keksdose.spoon.code_solver.TransformationEngine; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.QodanaRefactor; -import xyz.keksdose.spoon.code_solver.analyzer.qodana.QodanaRules; +import xyz.keksdose.spoon.code_solver.api.CodeRefactoring; import xyz.keksdose.spoon.code_solver.diffs.DiffCleaner; import xyz.keksdose.spoon.code_solver.history.Change; -import xyz.keksdose.spoon.code_solver.history.ChangeListener; import xyz.keksdose.spoon.code_solver.history.Changelog; -import xyz.keksdose.spoon.code_solver.transformations.TransformationProcessor; @ApplicationScoped public class RefactorService { @@ -121,18 +115,11 @@ private Promise createPullRequest( } if (message instanceof ProjectResult.Success success) { - ChangeListener listener = new ChangeListener(); - QodanaRefactor refactor = new QodanaRefactor(EnumSet.allOf(QodanaRules.class), listener, badSmells); - String refactorPath = success.project().folder().getAbsolutePath() + "/" + config.getSourceFolder(); - logger.atInfo().log("Refactoring %s", refactorPath); - Function> function = (v -> refactor); - TransformationEngine transformationEngine = new TransformationEngine(List.of(function)); - transformationEngine.setChangeListener(listener); - Changelog log = transformationEngine.applyToGivenPath(refactorPath); - log.getChanges() - .forEach(change -> - diffCleaner.clean(success.project().folder().toPath(), change)); try { + CodeRefactoring codeRefactoring = new CodeRefactoring(); + Changelog log = codeRefactoring.refactorBadSmells( + success.project().folder().toPath(), badSmells); + GitHub github = GitHub.connectUsingOAuth(System.getenv("GITHUB_TOKEN")); GHRepository repository = createForkIfMissing(success, github); GitHubUtils.createLabelIfMissing(repository);