diff --git a/pom.xml b/pom.xml index 819e09f02b4..51213799900 100644 --- a/pom.xml +++ b/pom.xml @@ -40,10 +40,22 @@ refactoring-miner ${rm.version} + + + + + + - junit - junit - 4.13.2 + org.junit.jupiter + junit-jupiter-api + 5.8.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.8.2 test @@ -130,7 +142,6 @@ jackson-databind 2.17.1 - diff --git a/src/main/java/org/codetracker/AnnotationTrackerChangeHistory.java b/src/main/java/org/codetracker/AnnotationTrackerChangeHistory.java index 925276d29c6..edb4829582f 100644 --- a/src/main/java/org/codetracker/AnnotationTrackerChangeHistory.java +++ b/src/main/java/org/codetracker/AnnotationTrackerChangeHistory.java @@ -140,7 +140,7 @@ public boolean checkForExtractionOrInline(Version currentVersion, Version parent } break; } - case EXTRACT_FIXTURE: +// case EXTRACT_FIXTURE:TODO: upgrade RM version then uncomment case MOVE_CODE: { MoveCodeRefactoring moveCodeRefactoring = (MoveCodeRefactoring) refactoring; Method extractedMethod = Method.of(moveCodeRefactoring.getTargetContainer(), currentVersion); diff --git a/src/main/java/org/codetracker/BlockTrackerChangeHistory.java b/src/main/java/org/codetracker/BlockTrackerChangeHistory.java index bf01484a079..10d97298bcb 100644 --- a/src/main/java/org/codetracker/BlockTrackerChangeHistory.java +++ b/src/main/java/org/codetracker/BlockTrackerChangeHistory.java @@ -2,17 +2,10 @@ import java.io.IOException; import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Predicate; - +import gr.uom.java.xmi.*; +import gr.uom.java.xmi.diff.*; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.tuple.Pair; import org.codetracker.api.History; @@ -37,6 +30,7 @@ import org.codetracker.change.method.BodyChange; import org.codetracker.element.Block; import org.codetracker.element.Method; +import org.codetracker.util.Util; import org.refactoringminer.api.Refactoring; import com.github.difflib.DiffUtils; @@ -46,11 +40,7 @@ import com.github.difflib.patch.InsertDelta; import com.github.difflib.patch.Patch; -import gr.uom.java.xmi.UMLOperation; -import gr.uom.java.xmi.UMLType; -import gr.uom.java.xmi.VariableDeclarationContainer; import gr.uom.java.xmi.LocationInfo.CodeElementType; -import gr.uom.java.xmi.UMLAnonymousClass; import gr.uom.java.xmi.decomposition.AbstractCodeFragment; import gr.uom.java.xmi.decomposition.AbstractCodeMapping; import gr.uom.java.xmi.decomposition.AbstractExpression; @@ -63,23 +53,9 @@ import gr.uom.java.xmi.decomposition.TryStatementObject; import gr.uom.java.xmi.decomposition.UMLOperationBodyMapper; import gr.uom.java.xmi.decomposition.VariableDeclaration; -import gr.uom.java.xmi.diff.ExtractOperationRefactoring; -import gr.uom.java.xmi.diff.InlineOperationRefactoring; -import gr.uom.java.xmi.diff.MergeOperationRefactoring; -import gr.uom.java.xmi.diff.MoveCodeRefactoring; -import gr.uom.java.xmi.diff.MoveOperationRefactoring; -import gr.uom.java.xmi.diff.PullUpOperationRefactoring; -import gr.uom.java.xmi.diff.PushDownOperationRefactoring; -import gr.uom.java.xmi.diff.RenameOperationRefactoring; -import gr.uom.java.xmi.diff.ReplaceAnonymousWithClassRefactoring; -import gr.uom.java.xmi.diff.ReplaceAnonymousWithLambdaRefactoring; -import gr.uom.java.xmi.diff.ReplaceConditionalWithTernaryRefactoring; -import gr.uom.java.xmi.diff.ReplaceLoopWithPipelineRefactoring; -import gr.uom.java.xmi.diff.ReplacePipelineWithLoopRefactoring; -import gr.uom.java.xmi.diff.SplitConditionalRefactoring; -import gr.uom.java.xmi.diff.SplitOperationRefactoring; -import gr.uom.java.xmi.diff.UMLAbstractClassDiff; -import gr.uom.java.xmi.diff.UMLAnonymousClassDiff; + +import static org.codetracker.util.CommentTransitionAnalyzer.*; + public class BlockTrackerChangeHistory extends AbstractChangeHistory { private final ChangeHistory blockChangeHistory = new ChangeHistory<>(); @@ -441,7 +417,7 @@ else if (mapping instanceof LeafMapping && mapping.getFragment1() instanceof Sta break; } */ - case EXTRACT_FIXTURE: +// case EXTRACT_FIXTURE: TODO: upgrade RM version then uncomment case MOVE_CODE: { MoveCodeRefactoring moveCodeRefactoring = (MoveCodeRefactoring) refactoring; Method extractedMethod = Method.of(moveCodeRefactoring.getTargetContainer(), currentVersion); @@ -693,9 +669,43 @@ public boolean checkBodyOfMatchedOperations(Version currentVersion, Version pare // check if it is in the matched if (isMatched(umlOperationBodyMapper, currentVersion, parentVersion, equalOperator)) return true; - //Check if is added + //check if block got uncommented + if(isBlockUncommented(umlOperationBodyMapper, currentVersion, parentVersion, equalOperator)){ + return true; + } +// Check if is added return isAdded(umlOperationBodyMapper, currentVersion, parentVersion, equalOperator); } + public boolean isBlockUncommented(UMLOperationBodyMapper umlOperationBodyMapper, Version currentVersion, Version parentVersion, Predicate equalOperator) { + List currentNonMappedInnerNodes = umlOperationBodyMapper.getNonMappedInnerNodesT2(); + UMLCommentListDiff umlCommentListDiff = umlOperationBodyMapper.getCommentListDiff(); + List deletedComments = umlCommentListDiff.getDeletedComments(); + if(currentNonMappedInnerNodes.size() == 0 || deletedComments == null || deletedComments.isEmpty()) + return false; + //reconstruct multiline block signature + Map allDeletedCommentsHashMap = generateCommentTextHashMap(deletedComments); + Map deletedCommentsBlockSignatureHashMap = generateUnCommentedBlockSignaturetHashMap(deletedComments); + if(deletedCommentsBlockSignatureHashMap.isEmpty()) + return false; + for(CompositeStatementObject nonMappedInnerNode : currentNonMappedInnerNodes) { + String normalizedSignature = nonMappedInnerNode.getActualSignature().replaceAll("\\s+", " ").trim(); + String hashOfNonMappedInnerNode = Util.getSHA512(normalizedSignature); + if (!deletedCommentsBlockSignatureHashMap.containsKey(hashOfNonMappedInnerNode)) + continue; + Block blockAfter = Block.of(nonMappedInnerNode, umlOperationBodyMapper.getContainer2(), currentVersion); + if (!equalOperator.test(blockAfter)) + continue; + //check block body continuity + if (!isBlockBodyUnchangedDuringUncomment(umlOperationBodyMapper, nonMappedInnerNode, allDeletedCommentsHashMap, blockAfter)) + continue; + Block virtualBlockBefore = Block.of(nonMappedInnerNode, umlOperationBodyMapper.getContainer2(), parentVersion); // add metadata later, flag isVirtual = true; + blockChangeHistory.addChange(virtualBlockBefore, blockAfter, ChangeFactory.forBlock(Change.Type.UNCOMMENTED_BLOCK)); + elements.add(virtualBlockBefore); + blockChangeHistory.connectRelatedNodes(); + return true; + } + return false; + } public boolean isBlockRefactored(Collection refactorings, Version currentVersion, Version parentVersion, Predicate equalOperator) { Set leftBlockSet = analyseBlockRefactorings(refactorings, currentVersion, parentVersion, equalOperator); @@ -1137,7 +1147,16 @@ public boolean isMatched(UMLOperationBodyMapper umlOperationBodyMapper, Version List stringRepresentationBodyBefore = stringRepresentationBefore.subList(1, stringRepresentationBefore.size()); List stringRepresentationBodyAfter = stringRepresentationAfter.subList(1, stringRepresentationAfter.size()); if (!stringRepresentationBodyBefore.equals(stringRepresentationBodyAfter)) { - blockChangeHistory.addChange(blockBefore, blockAfter, ChangeFactory.forBlock(Change.Type.BODY_CHANGE)); + Set commentTransitions = detectCommentTransitionsInsideMatchedBlock(umlOperationBodyMapper, blockBefore, blockAfter, currentVersion, parentVersion); + if(!commentTransitions.isEmpty()){ + for(Change.Type changeType : commentTransitions){ + blockChangeHistory.addChange(blockBefore, blockAfter, ChangeFactory.forBlock(changeType)); + } + } + else{ + blockChangeHistory.addChange(blockBefore, blockAfter, ChangeFactory.forBlock(Change.Type.BODY_CHANGE)); + } + } bodyChange = true; } diff --git a/src/main/java/org/codetracker/CommentTrackerChangeHistory.java b/src/main/java/org/codetracker/CommentTrackerChangeHistory.java index df05cc0853f..c45904e322c 100644 --- a/src/main/java/org/codetracker/CommentTrackerChangeHistory.java +++ b/src/main/java/org/codetracker/CommentTrackerChangeHistory.java @@ -317,7 +317,7 @@ public boolean checkForExtractionOrInline(Version currentVersion, Version parent } break; } - case EXTRACT_FIXTURE: +// case EXTRACT_FIXTURE:TODO: upgrade RM version then uncomment case MOVE_CODE: { MoveCodeRefactoring moveCodeRefactoring = (MoveCodeRefactoring) refactoring; Method extractedMethod = Method.of(moveCodeRefactoring.getTargetContainer(), currentVersion); diff --git a/src/main/java/org/codetracker/Main.java b/src/main/java/org/codetracker/Main.java index 15293045808..86516fdde9d 100644 --- a/src/main/java/org/codetracker/Main.java +++ b/src/main/java/org/codetracker/Main.java @@ -16,51 +16,23 @@ import java.time.ZoneOffset; public class Main { - private final static String FOLDER_TO_CLONE = "tmp/"; +// private final static String FOLDER_TO_CLONE = "tmp/"; + private final static String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + private final static String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + public static void main(String args[]) throws Exception { GitService gitService = new GitServiceImpl(); - // BLOCK TRACKING EXAMPLE - try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", - "https://github.com/checkstyle/checkstyle.git")){ - - BlockTracker blockTracker = CodeTracker.blockTracker() - .repository(repository) - .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") - .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") - .methodName("fireErrors") - .methodDeclarationLineNumber(384) - .codeElementType(CodeElementType.ENHANCED_FOR_STATEMENT) - .blockStartLineNumber(391) - .blockEndLineNumber(393) - .build(); - - History blockHistory = blockTracker.track(); - - for (History.HistoryInfo historyInfo : blockHistory.getHistoryInfoList()) { - System.out.println("======================================================"); - System.out.println("Commit ID: " + historyInfo.getCommitId()); - System.out.println("Date: " + - LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); - System.out.println("Before: " + historyInfo.getElementBefore().getName()); - System.out.println("After: " + historyInfo.getElementAfter().getName()); - - for (Change change : historyInfo.getChangeList()) { - System.out.println(change.getType().getTitle() + ": " + change); - } - } - System.out.println("======================================================"); - } // METHOD TRACKING EXAMPLE - try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", - "https://github.com/checkstyle/checkstyle.git")){ + try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE)){ MethodTracker methodTracker = CodeTracker.methodTracker() .repository(repository) - .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") - .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") - .methodName("fireErrors") - .methodDeclarationLineNumber(384) + .filePath("CryptoServer/src/main/java/com/cryptography/service/CryptoService.java") + .startCommitId("d0d9edcfb611ee35978938f7e35250f1ae982057") + .methodName("ceateUser") + .methodDeclarationLineNumber(43) .build(); History methodHistory = methodTracker.track(); @@ -79,65 +51,125 @@ public static void main(String args[]) throws Exception { } System.out.println("======================================================"); } - // VARIABLE TRACKING EXAMPLE - try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", - "https://github.com/checkstyle/checkstyle.git")){ - - VariableTracker variableTracker = CodeTracker.variableTracker() - .repository(repository) - .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") - .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") - .methodName("fireErrors") - .methodDeclarationLineNumber(384) - .variableName("stripped") - .variableDeclarationLineNumber(385) - .build(); - - History variableHistory = variableTracker.track(); - for (History.HistoryInfo historyInfo : variableHistory.getHistoryInfoList()) { - System.out.println("======================================================"); - System.out.println("Commit ID: " + historyInfo.getCommitId()); - System.out.println("Date: " + - LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); - System.out.println("Before: " + historyInfo.getElementBefore().getName()); - System.out.println("After: " + historyInfo.getElementAfter().getName()); - - for (Change change : historyInfo.getChangeList()) { - System.out.println(change.getType().getTitle() + ": " + change); - } - } - System.out.println("======================================================"); - } - - // ATTRIBUTE TRACKING EXAMPLE - try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", - "https://github.com/checkstyle/checkstyle.git")) { - - AttributeTracker attributeTracker = CodeTracker.attributeTracker() - .repository(repository) - .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") - .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") - .attributeName("cacheFile") - .attributeDeclarationLineNumber(132) - .build(); - - History attributeHistory = attributeTracker.track(); - - for (History.HistoryInfo historyInfo : attributeHistory.getHistoryInfoList()) { - System.out.println("======================================================"); - System.out.println("Commit ID: " + historyInfo.getCommitId()); - System.out.println("Date: " + - LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); - System.out.println("Before: " + historyInfo.getElementBefore().getName()); - System.out.println("After: " + historyInfo.getElementAfter().getName()); - - for (Change change : historyInfo.getChangeList()) { - System.out.println(change.getType().getTitle() + ": " + change); - } - } - System.out.println("======================================================"); - } +// // BLOCK TRACKING EXAMPLE +// try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", +// "https://github.com/checkstyle/checkstyle.git")){ +// +// BlockTracker blockTracker = CodeTracker.blockTracker() +// .repository(repository) +// .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") +// .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") +// .methodName("fireErrors") +// .methodDeclarationLineNumber(384) +// .codeElementType(CodeElementType.ENHANCED_FOR_STATEMENT) +// .blockStartLineNumber(391) +// .blockEndLineNumber(393) +// .build(); +// +// History blockHistory = blockTracker.track(); +// +// for (History.HistoryInfo historyInfo : blockHistory.getHistoryInfoList()) { +// System.out.println("======================================================"); +// System.out.println("Commit ID: " + historyInfo.getCommitId()); +// System.out.println("Date: " + +// LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); +// System.out.println("Before: " + historyInfo.getElementBefore().getName()); +// System.out.println("After: " + historyInfo.getElementAfter().getName()); +// +// for (Change change : historyInfo.getChangeList()) { +// System.out.println(change.getType().getTitle() + ": " + change); +// } +// } +// System.out.println("======================================================"); +// } +// // METHOD TRACKING EXAMPLE +// try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", +// "https://github.com/checkstyle/checkstyle.git")){ +// +// MethodTracker methodTracker = CodeTracker.methodTracker() +// .repository(repository) +// .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") +// .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") +// .methodName("fireErrors") +// .methodDeclarationLineNumber(384) +// .build(); +// +// History methodHistory = methodTracker.track(); +// +// for (History.HistoryInfo historyInfo : methodHistory.getHistoryInfoList()) { +// System.out.println("======================================================"); +// System.out.println("Commit ID: " + historyInfo.getCommitId()); +// System.out.println("Date: " + +// LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); +// System.out.println("Before: " + historyInfo.getElementBefore().getName()); +// System.out.println("After: " + historyInfo.getElementAfter().getName()); +// +// for (Change change : historyInfo.getChangeList()) { +// System.out.println(change.getType().getTitle() + ": " + change); +// } +// } +// System.out.println("======================================================"); +// } +// // VARIABLE TRACKING EXAMPLE +// try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", +// "https://github.com/checkstyle/checkstyle.git")){ +// +// VariableTracker variableTracker = CodeTracker.variableTracker() +// .repository(repository) +// .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") +// .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") +// .methodName("fireErrors") +// .methodDeclarationLineNumber(384) +// .variableName("stripped") +// .variableDeclarationLineNumber(385) +// .build(); +// +// History variableHistory = variableTracker.track(); +// +// for (History.HistoryInfo historyInfo : variableHistory.getHistoryInfoList()) { +// System.out.println("======================================================"); +// System.out.println("Commit ID: " + historyInfo.getCommitId()); +// System.out.println("Date: " + +// LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); +// System.out.println("Before: " + historyInfo.getElementBefore().getName()); +// System.out.println("After: " + historyInfo.getElementAfter().getName()); +// +// for (Change change : historyInfo.getChangeList()) { +// System.out.println(change.getType().getTitle() + ": " + change); +// } +// } +// System.out.println("======================================================"); +// } +// +// // ATTRIBUTE TRACKING EXAMPLE +// try (Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE + "checkstyle\\checkstyle", +// "https://github.com/checkstyle/checkstyle.git")) { +// +// AttributeTracker attributeTracker = CodeTracker.attributeTracker() +// .repository(repository) +// .filePath("src/main/java/com/puppycrawl/tools/checkstyle/Checker.java") +// .startCommitId("119fd4fb33bef9f5c66fc950396669af842c21a3") +// .attributeName("cacheFile") +// .attributeDeclarationLineNumber(132) +// .build(); +// +// History attributeHistory = attributeTracker.track(); +// +// for (History.HistoryInfo historyInfo : attributeHistory.getHistoryInfoList()) { +// System.out.println("======================================================"); +// System.out.println("Commit ID: " + historyInfo.getCommitId()); +// System.out.println("Date: " + +// LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); +// System.out.println("Before: " + historyInfo.getElementBefore().getName()); +// System.out.println("After: " + historyInfo.getElementAfter().getName()); +// +// for (Change change : historyInfo.getChangeList()) { +// System.out.println(change.getType().getTitle() + ": " + change); +// } +// } +// System.out.println("======================================================"); +// } } } diff --git a/src/main/java/org/codetracker/MethodTrackerChangeHistory.java b/src/main/java/org/codetracker/MethodTrackerChangeHistory.java index bbb1cbb38a2..e654d863047 100644 --- a/src/main/java/org/codetracker/MethodTrackerChangeHistory.java +++ b/src/main/java/org/codetracker/MethodTrackerChangeHistory.java @@ -448,7 +448,7 @@ else if (looserMapper(mapperWithLessMappings, mapper)) { } break; } - case EXTRACT_FIXTURE: +// case EXTRACT_FIXTURE: TODO: upgrade RM version then uncomment case MOVE_CODE: { MoveCodeRefactoring moveCodeRefactoring = (MoveCodeRefactoring) refactoring; operationBefore = moveCodeRefactoring.getSourceContainer(); diff --git a/src/main/java/org/codetracker/VariableTrackerChangeHistory.java b/src/main/java/org/codetracker/VariableTrackerChangeHistory.java index 848c6e7465f..4a0cbb52840 100644 --- a/src/main/java/org/codetracker/VariableTrackerChangeHistory.java +++ b/src/main/java/org/codetracker/VariableTrackerChangeHistory.java @@ -238,7 +238,7 @@ public boolean checkForExtractionOrInline(Version currentVersion, Version parent } break; } - case EXTRACT_FIXTURE: +// case EXTRACT_FIXTURE: TODO: upgrade RM version then uncomment case MOVE_CODE: { MoveCodeRefactoring moveCodeRefactoring = (MoveCodeRefactoring) refactoring; Method extractedMethod = Method.of(moveCodeRefactoring.getTargetContainer(), currentVersion); diff --git a/src/main/java/org/codetracker/change/Change.java b/src/main/java/org/codetracker/change/Change.java index 0eca191d9b1..e3ffd031dd2 100644 --- a/src/main/java/org/codetracker/change/Change.java +++ b/src/main/java/org/codetracker/change/Change.java @@ -56,8 +56,10 @@ enum Type { INITIALIZER_ADDED("initializer added"), INITIALIZER_REMOVED("initializer removed"), SUPERCLASS_CHANGE("superclass change"), - INTERFACE_LIST_CHANGE("interface list change"); - + INTERFACE_LIST_CHANGE("interface list change"), + COMMENTED_OUT_STATEMENT("commented out statement"), + UNCOMMENTED_STATEMENT("uncommented statement"), + UNCOMMENTED_BLOCK("uncommented Block"); private static final Map lookup = new HashMap<>(); static { diff --git a/src/main/java/org/codetracker/change/ChangeFactory.java b/src/main/java/org/codetracker/change/ChangeFactory.java index 405b85aa30d..78cdf3ad153 100644 --- a/src/main/java/org/codetracker/change/ChangeFactory.java +++ b/src/main/java/org/codetracker/change/ChangeFactory.java @@ -141,6 +141,19 @@ public AbstractChange build() { change = new BodyChange(); break; } + case UNCOMMENTED_STATEMENT:{ + change = new UncommentedCodeInBlock(); + break; + } + case COMMENTED_OUT_STATEMENT:{ + change = new CommentedOutCodeInBlock(); + break; + } + case UNCOMMENTED_BLOCK:{ + change = new UncommentedBlock(); + break; + } + case CATCH_BLOCK_CHANGE: { change = new CatchBlockChange(); break; diff --git a/src/main/java/org/codetracker/change/block/CommentedOutCodeInBlock.java b/src/main/java/org/codetracker/change/block/CommentedOutCodeInBlock.java new file mode 100644 index 00000000000..f7469135110 --- /dev/null +++ b/src/main/java/org/codetracker/change/block/CommentedOutCodeInBlock.java @@ -0,0 +1,13 @@ +package org.codetracker.change.block; + +public class CommentedOutCodeInBlock extends BlockBodyChange { + public CommentedOutCodeInBlock() { + super(Type.COMMENTED_OUT_STATEMENT); + } + + @Override + public String toString() { + return "Body Change, Contains Commented-out Code"; + } + +} diff --git a/src/main/java/org/codetracker/change/block/UncommentedBlock.java b/src/main/java/org/codetracker/change/block/UncommentedBlock.java new file mode 100644 index 00000000000..df8c71c3620 --- /dev/null +++ b/src/main/java/org/codetracker/change/block/UncommentedBlock.java @@ -0,0 +1,13 @@ +package org.codetracker.change.block; + +public class UncommentedBlock extends BlockChange { + public UncommentedBlock() { + super(Type.UNCOMMENTED_BLOCK); + } + + @Override + public String toString() { + return "Block Change, Uncommented Block"; + } + +} diff --git a/src/main/java/org/codetracker/change/block/UncommentedCodeInBlock.java b/src/main/java/org/codetracker/change/block/UncommentedCodeInBlock.java new file mode 100644 index 00000000000..9f940f99931 --- /dev/null +++ b/src/main/java/org/codetracker/change/block/UncommentedCodeInBlock.java @@ -0,0 +1,15 @@ +package org.codetracker.change.block; + +import org.codetracker.change.Change; + +public class UncommentedCodeInBlock extends BlockBodyChange { + public UncommentedCodeInBlock() { + super(Change.Type.UNCOMMENTED_STATEMENT); + } + + @Override + public String toString() { + return "Body Change, Contains Uncommented Code"; + } + +} diff --git a/src/main/java/org/codetracker/util/CommentTransitionAnalyzer.java b/src/main/java/org/codetracker/util/CommentTransitionAnalyzer.java new file mode 100644 index 00000000000..e33c4941e63 --- /dev/null +++ b/src/main/java/org/codetracker/util/CommentTransitionAnalyzer.java @@ -0,0 +1,395 @@ +package org.codetracker.util; + +import gr.uom.java.xmi.LocationInfo; +import gr.uom.java.xmi.UMLComment; +import gr.uom.java.xmi.decomposition.*; +import org.codetracker.api.Version; +import org.codetracker.change.Change; +import org.codetracker.element.Block; + +import java.util.*; + +public class CommentTransitionAnalyzer { + + public static Set detectCommentTransitionsInsideMatchedBlock(UMLOperationBodyMapper umlOperationBodyMapper, Block blockBefore, Block blockAfter, Version currentVersion, Version parentVersion) { + Set changeTypes = new HashSet<>(); + List deletedComments = umlOperationBodyMapper.getCommentListDiff().getDeletedComments(); + List addedComments = umlOperationBodyMapper.getCommentListDiff().getAddedComments(); + Map deletedCommentsHash; + Map addedCommentsHash; + + if (!deletedComments.isEmpty()) { + List inScopeDeletedComments; + inScopeDeletedComments = removeOutOfScopeComments(deletedComments, blockBefore); + deletedCommentsHash = generateCommentTextHashMap(inScopeDeletedComments); + if (isUncommentedCodeDetected(deletedCommentsHash, umlOperationBodyMapper, blockAfter)) { + changeTypes.add(Change.Type.UNCOMMENTED_STATEMENT); + } + } + if (!addedComments.isEmpty()) { + List inScopeAddedComments; + inScopeAddedComments = removeOutOfScopeComments(addedComments, blockAfter); + addedCommentsHash = generateCommentTextHashMap(inScopeAddedComments); + if (isCommentedOutCodeDetected(addedCommentsHash, umlOperationBodyMapper, blockBefore)) { + changeTypes.add(Change.Type.COMMENTED_OUT_STATEMENT); + } + } + return changeTypes; + } + private static List removeOutOfScopeComments(List commentList, Block block){ + List inScopeComments = new ArrayList<>(); + for (int i = 0; i < commentList.size(); i++) { + if ((commentList.get(i).getLocationInfo().getStartLine() > block.getLocation().getStartLine() && + commentList.get(i).getLocationInfo().getEndLine() < block.getLocation().getEndLine())) { + inScopeComments.add(commentList.get(i)); + } + } + return inScopeComments; + } + private static boolean isUncommentedCodeDetected(Map deletedCommentsHash, UMLOperationBodyMapper umlOperationBodyMapper, Block blockAfter) { + if (deletedCommentsHash.isEmpty()) + return false; + // find unmatched leaf statements afterBlock in deleted comments + if (!umlOperationBodyMapper.getNonMappedLeavesT2().isEmpty()) { + for (AbstractCodeFragment abstractCodeFragment : umlOperationBodyMapper.getNonMappedLeavesT2()) { + if (blockAfter.getComposite().getLeaves().contains(abstractCodeFragment)) { //if nonmappedLeave actually belongs to the target Block + String codeFragmentHash = Util.getSHA512(abstractCodeFragment.getString().trim()); + if (deletedCommentsHash.containsKey(codeFragmentHash)) { + return true; + } + } + } + } + //find unmatched composite statements afterBlock in deleted comments + if (!umlOperationBodyMapper.getNonMappedInnerNodesT2().isEmpty()) { + for (CompositeStatementObject compositeStatementObject : umlOperationBodyMapper.getNonMappedInnerNodesT2()) { + if (((CompositeStatementObject) blockAfter.getComposite()).contains(compositeStatementObject)) { //if nonMappedInnerNode actually belongs to the current block + String codeFragmentHash = Util.getSHA512(compositeStatementObject.getActualSignature()); + if (deletedCommentsHash.containsKey(codeFragmentHash)) { + return true; + } + } + } + } + // RefactoringMiner may create leaf mappings between semantically different statements when textual similarity is high enough, + // even when one side is actually a commented/uncommented transition. + if (!umlOperationBodyMapper.getMappings().isEmpty()) { + for (AbstractCodeMapping mapping : umlOperationBodyMapper.getMappings()) { + if (!(mapping instanceof LeafMapping)) // does not happen in composite + continue; + if(mapping.getReplacements().isEmpty()) //real mapping + continue; + if (!isMappingBelongToTrackedBlock(mapping, blockAfter, true)) + continue; + String codeFragmentHashCurrent = Util.getSHA512(mapping.getFragment2().getString().trim()); + if (deletedCommentsHash.containsKey(codeFragmentHashCurrent)) { + return true; + } + } + } + return false; + } + + private static boolean isCommentedOutCodeDetected(Map addedCommentsHash, UMLOperationBodyMapper umlOperationBodyMapper, Block blockBefore) { + if (addedCommentsHash.isEmpty()) + return false; + if (!umlOperationBodyMapper.getNonMappedLeavesT1().isEmpty()) { + //find unmatched leaf statements parent1 in added comments + for (AbstractCodeFragment abstractCodeFragment : umlOperationBodyMapper.getNonMappedLeavesT1()) { + if (blockBefore.getComposite().getLeaves().contains(abstractCodeFragment)) { // if nonMappedleaf actually belongs to parent block + String codeFragmentHash = Util.getSHA512(abstractCodeFragment.getString().trim()); + if (addedCommentsHash.containsKey(codeFragmentHash)) { + return true; + } + } + } + } + if (!umlOperationBodyMapper.getNonMappedInnerNodesT1().isEmpty()) { + //find unmatched composite statements parent in added comments + for (CompositeStatementObject compositeStatementObject : umlOperationBodyMapper.getNonMappedInnerNodesT1()) { + if (((CompositeStatementObject) blockBefore.getComposite()).contains(compositeStatementObject)) { // if nonMappedInnerNode actually belongs to parent block + if (!isBracketAndBelongsToStandAloneBlock(compositeStatementObject)) + continue; + String codeFragmentHash = Util.getSHA512(compositeStatementObject.getActualSignature()); + if (addedCommentsHash.containsKey(codeFragmentHash)) { + return true; + } + } + } + } + // RefactoringMiner may create leaf mappings between semantically different statements when textual similarity is high enough, + // even when one side is actually a commented/uncommented transition. + if (!umlOperationBodyMapper.getMappings().isEmpty()) { + for (AbstractCodeMapping mapping : umlOperationBodyMapper.getMappings()) { + if (!(mapping instanceof LeafMapping)) // does not happen in composite + continue; + if(mapping.getReplacements().isEmpty()) //real mapping + continue; + if (!isMappingBelongToTrackedBlock(mapping, blockBefore, false)) + continue; + String codeFragmentHashParent = Util.getSHA512(mapping.getFragment1().getString().trim()); + if (!addedCommentsHash.isEmpty() && addedCommentsHash.containsKey(codeFragmentHashParent)) { + return true; + } + } + } + return false; + } + public static boolean isBlockBodyUnchangedDuringUncomment (UMLOperationBodyMapper umlOperationBodyMapper, CompositeStatementObject uncommentedBlock, Map deletedComments, Block blockAfter) { + Set mappedFragments = new HashSet<>(); + for (AbstractCodeMapping mapping : umlOperationBodyMapper.getMappings()) { + if(!isMappingBelongToTrackedBlock(mapping, blockAfter, true)) + continue; + if(mapping instanceof CompositeStatementObjectMapping) { + CompositeStatementObject composite = (CompositeStatementObject) mapping.getFragment2(); + if (!isBracketAndBelongsToStandAloneBlock(composite)) + continue; + mappedFragments.add(Util.getSHA512(composite.getActualSignature())); + } + else if(mapping instanceof LeafMapping && mapping.getFragment2() instanceof StatementObject){ // mappings belong to the currentblock + mappedFragments.add(Util.getSHA512(mapping.getFragment2().getString().trim())); + } + } + for (CompositeStatementObject inner : uncommentedBlock.getInnerNodes()) { + if(inner.getActualSignature().equals(uncommentedBlock.getActualSignature())){ + continue; + } + if (!isBracketAndBelongsToStandAloneBlock(inner)) { + continue; + } + String hash = Util.getSHA512(inner.getActualSignature().replaceAll("\\s+", " ").trim()); + if(!existsAsMappedOrComment(hash, mappedFragments, deletedComments)){ + return false; + } + } + for (AbstractCodeFragment leaf : uncommentedBlock.getLeaves()) { + String hash = Util.getSHA512(((StatementObject) leaf).getActualSignature().replaceAll("\\s+", " ").trim()); + if(!existsAsMappedOrComment(hash, mappedFragments, deletedComments)) + return false; + } + return true; + } + + private static Change.Type partialBlockUncommented(CompositeStatementObject compositeStatementObject, Block blockBefore, Block blockAfter) { + //TODO: else/catch/finally uncommented support should be added + if (blockBefore.getComposite().getLocationInfo().getCodeElementType().equals(LocationInfo.CodeElementType.IF_STATEMENT) && + blockAfter.getComposite().getLocationInfo().getCodeElementType().equals(LocationInfo.CodeElementType.IF_STATEMENT)) { + CompositeStatementObject ifBefore = (CompositeStatementObject) blockBefore.getComposite(); + CompositeStatementObject ifAfter = (CompositeStatementObject) blockAfter.getComposite(); + if (ifBefore.getStatements().size() == 1 && ifAfter.getStatements().size() == 2) { + return Change.Type.UNCOMMENTED_STATEMENT; + } + } + return null; + } + + public static boolean isBracketAndBelongsToStandAloneBlock(CompositeStatementObject compositeStatementObject){ //heuristic + if ((compositeStatementObject.getLocationInfo().getCodeElementType() == LocationInfo.CodeElementType.BLOCK) && (!compositeStatementObject.getParent().getActualSignature().equals("{"))) + return false; + return true; + } + private static boolean isMappingBelongToTrackedBlock(AbstractCodeMapping mapping, Block block, boolean isAfter){ + if(mapping instanceof CompositeStatementObjectMapping){ + CompositeStatementObject composite = (CompositeStatementObject) mapping.getFragment2(); + if(!((CompositeStatementObject) block.getComposite()).contains(composite)) + return false; + } + else if(mapping instanceof LeafMapping && (isAfter ? mapping.getFragment2() : mapping.getFragment1()) instanceof StatementObject){ + if(!block.getComposite().getLeaves().contains(isAfter ? mapping.getFragment2() : mapping.getFragment1())) + return false; + } + return true; + } + private static boolean existsAsMappedOrComment(String hash, Set mappedFragments, Map commentsHash){ + return mappedFragments.contains(hash) || commentsHash.containsKey(hash); + } + public static String normalizeCommentText(String commentText) { + commentText = commentText.trim(); + if (commentText.startsWith("//")) { + commentText = commentText.substring(2); + } + if (commentText.startsWith("/*")) { + commentText = commentText.substring(2); + } + if (commentText.endsWith("*/")) { + commentText = commentText.substring(0, commentText.length() - 2); + } + commentText = commentText.trim(); + if (commentText.startsWith("*")) { + commentText = commentText.substring(1); + } + return commentText.trim(); + } + + public static Map generateCommentTextHashMap(List commentList) { + Map commentTextHashMap = new HashMap<>(); + for (UMLComment comment : commentList) { + String text = comment.getText(); + text = normalizeCommentText(text); + if(comment.getFullText().startsWith("/*")){ + commentTextHashMap.put(Util.getSHA512(text.replaceAll("\\s+", " ").trim()), comment); + } + String[] lines = text.split("\\R"); + for (String line : lines) { + line = normalizeCommentText(line); + if (line.isBlank()) { + continue; + } + commentTextHashMap.put(Util.getSHA512(line), comment); + } + } + return commentTextHashMap; + } + public static Map generateUnCommentedBlockSignaturetHashMap(List commentList) { + Map blockSignatureUnCommentedHashMap = new HashMap<>(); + List blockSignatureUnCommented = extractBlockSignaturesFromComments(commentList); + for(String signature : blockSignatureUnCommented){ + String normalized = signature.replaceAll("\\s+", " ").trim(); + blockSignatureUnCommentedHashMap.put(Util.getSHA512(normalized), normalized); + } + return blockSignatureUnCommentedHashMap; + } +public static List extractBlockSignaturesFromComments(List comments) { + List signatures = new ArrayList<>(); + + for (int i = 0; i < comments.size(); i++) { + UMLComment comment = comments.get(i); + String text = normalizeCommentText(comment.getText()); + if (text.isBlank()) + continue; + if (isLeafStatement(text)) + continue; + // Complete one-line signature + if (isCompleteBlockSignature(text)) { + signatures.add(text); + continue; + } + if (comment.getFullText().startsWith("/*")) { + signatures.addAll(extractFromBlockComment(text)); + } + else if (comment.getFullText().startsWith("//")) { + if (!hasBlockKeyword(text)) + continue; + SingleLineExtractionResult singleLineExtractionResult = extractFromSingleLineComments(comments, i, text); + signatures.addAll(singleLineExtractionResult.getSignatures()); + i = singleLineExtractionResult.getLastConsumedIndex(); + } + } + return signatures; +} +private static boolean isCompleteBlockSignature(String text) { + return hasBlockKeyword(text) && text.trim().endsWith("{"); + } + private static boolean signatureEnds(String text) { + return text.trim().endsWith("{"); + } + private static boolean hasBlockKeyword(String text) { + String trimmed = text.trim(); + return trimmed.startsWith("if") + || trimmed.startsWith("else") + || trimmed.startsWith("for") + || trimmed.startsWith("while") + || trimmed.startsWith("do") + || trimmed.startsWith("try") + || trimmed.startsWith("catch") + || trimmed.startsWith("finally") + || trimmed.startsWith("switch") + || trimmed.startsWith("synchronized") + || trimmed.startsWith("static"); + //TODO:Add support for standalone block {} + } + private static boolean areConsecutiveComments( + UMLComment current, + UMLComment next) { + + return next.getLocationInfo().getStartLine() + == current.getLocationInfo().getEndLine() + 1; + } + private static boolean isLeafStatement(String text) { + return (!hasBlockKeyword(text) && text.trim().endsWith(";")); + } + + private static List extractFromBlockComment(String commentText) { + List signatures = new ArrayList<>(); + String[] lines = commentText.split("\\R"); + for (int j = 0; j < lines.length; j++) { + if (isLeafStatement(lines[j])) + continue; + if (!hasBlockKeyword(lines[j])) + continue; + StringBuilder signatureBuilder = new StringBuilder(); + signatureBuilder.append(lines[j]); + int currentIndex = j + 1; + while (!signatureEnds(signatureBuilder.toString()) + && currentIndex < lines.length) { + String nextLine = lines[currentIndex]; + if (isLeafStatement(nextLine)) { + if (signatureBuilder.toString().trim().endsWith(")")) { + signatures.add(signatureBuilder.toString()); + } + break; + } + // another block signature starts + if (hasBlockKeyword(nextLine)) + break; + signatureBuilder.append("\n").append(nextLine); + currentIndex++; + } + if (signatureEnds(signatureBuilder.toString())) { + signatures.add(signatureBuilder.toString()); + } + j = currentIndex - 1; + } + return signatures; + } + + private static SingleLineExtractionResult extractFromSingleLineComments(List comments, int index, String commentText){ + int lastConsumedIndex = index; + List signatures = new ArrayList<>(); + StringBuilder signatureBuilder = new StringBuilder(); + signatureBuilder.append(commentText); + int currentIndex = index; + while (!signatureEnds(signatureBuilder.toString()) + && currentIndex + 1 < comments.size()) { + UMLComment current = comments.get(currentIndex); + UMLComment next = comments.get(currentIndex + 1); + if (!areConsecutiveComments(current, next)) + break; + String nextText = normalizeCommentText(next.getText()); + if (isLeafStatement(nextText)) { + if (signatureBuilder.toString().trim().endsWith(")")) { + signatures.add(signatureBuilder.toString()); + } + break; + } + // another block signature starts inside the same comment + if (hasBlockKeyword(nextText)) + break; + signatureBuilder.append("\n").append(nextText); + currentIndex++; + } + if (signatureEnds(signatureBuilder.toString())) { + signatures.add(signatureBuilder.toString()); + lastConsumedIndex = currentIndex; + } + return new SingleLineExtractionResult(signatures, lastConsumedIndex); + } + private static class SingleLineExtractionResult { + private List signatures; + private int lastConsumedIndex; + + SingleLineExtractionResult(List signatures, + int lastConsumedIndex) { + this.signatures = signatures; + this.lastConsumedIndex = lastConsumedIndex; + } + public List getSignatures() { + return signatures; + } + + public int getLastConsumedIndex() { + return lastConsumedIndex; + } + } +} + diff --git a/src/test/java/org/codetracker/AttributeTrackerImplTest.java b/src/test/java/org/codetracker/AttributeTrackerImplTest.java new file mode 100644 index 00000000000..aab4144716d --- /dev/null +++ b/src/test/java/org/codetracker/AttributeTrackerImplTest.java @@ -0,0 +1,58 @@ +package org.codetracker; + +import org.codetracker.api.AttributeTracker; +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.change.Change; +import org.codetracker.element.Attribute; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class AttributeTrackerImplTest { + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + + @Test + public void returnFalseRename() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + + AttributeTracker attributeTracker = CodeTracker.attributeTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/genericcase/ServiceInfo.java") + .startCommitId("88cbdb012a2e92d029f20b5253272f32ce84c3be") + .attributeName("serviceName") + .attributeDeclarationLineNumber(3) + .build(); + History attributeHistory = attributeTracker.track(); + printHappyCaseOutput(attributeHistory); + assertNotNull(attributeHistory); + assertTrue(!attributeHistory.getHistoryInfoList().isEmpty() && attributeHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + private void printHappyCaseOutput(History attributeHistory){ + for (History.HistoryInfo historyInfo : attributeHistory.getHistoryInfoList()) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + historyInfo.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("Before: " + historyInfo.getElementBefore().getName()); + System.out.println("After: " + historyInfo.getElementAfter().getName()); + + for (Change change : historyInfo.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + } + System.out.println("======================================================"); + } + + } diff --git a/src/test/java/org/codetracker/BlameTest.java b/src/test/java/org/codetracker/BlameTest.java new file mode 100644 index 00000000000..b32b60e109c --- /dev/null +++ b/src/test/java/org/codetracker/BlameTest.java @@ -0,0 +1,122 @@ +package org.codetracker; + +import gr.uom.java.xmi.LocationInfo; +import org.codetracker.api.BlockTracker; +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.api.MethodTracker; +import org.codetracker.change.Change; +import org.codetracker.element.Block; +import org.codetracker.element.Method; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BlameTest { + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + + /*************************************************************************** + * ************************************* + * Blame + * False Rename Detection Instead Of Extract Class & Move Method + * ************************************* + */ + @Test + public void returnBlameWhenExtractClassNew() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/newclass/Calculator.java") + .startCommitId("8ef06dced725cca8cc22705d4eba95ef39ae1e36") + .methodName("print") + .methodDeclarationLineNumber(17) + .build(); + History.HistoryInfo methodHistory = methodTracker.blame(); + printHappyCaseOutputMethod(methodHistory); + assertNotNull(methodHistory); +// assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + + @Test + public void returnsBlameRenameMethodGivenCommitInfoOfRepository() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/service/CryptoService.java") + .startCommitId("d0d9edcfb611ee35978938f7e35250f1ae982057") + .methodName("ceateUser") + .methodDeclarationLineNumber(46) //54 43 + .build(); + History.HistoryInfo methodHistory = methodTracker.blame(); + printHappyCaseOutputMethod(methodHistory); + assertNotNull(methodHistory); +// assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().size() > 2); + } + + @Test + public void ifToTernaryOperatorTest() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + BlockTracker blockTracker = CodeTracker.blockTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/blocktracking/ternary/Main.java") + .startCommitId("3b7a3dfdbc8c9a6233a7d631bc9ff1eb35bc0653") + .methodName("isPassed") + .methodDeclarationLineNumber(5) + .codeElementType(LocationInfo.CodeElementType.RETURN_STATEMENT) + .blockStartLineNumber(6) + .blockEndLineNumber(6) + .blameLineNumber(6) + .build(); + + History.HistoryInfo blockHistory = blockTracker.blame(); + printHappyCaseOutputBlock(blockHistory); + assertNotNull(blockHistory); +// assertTrue(!blockHistory.getHistoryInfoList().isEmpty() && blockHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + + private void printHappyCaseOutputBlock(History.HistoryInfo blockHistory) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + blockHistory.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(blockHistory.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("CommitterName: " + blockHistory.getCommitterName()); + System.out.println("Before: " + blockHistory.getElementBefore().getName()); + System.out.println("After: " + blockHistory.getElementAfter().getName()); + + for (Change change : blockHistory.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + System.out.println("======================================================"); + } + + private void printHappyCaseOutputMethod(History.HistoryInfo methodHistory) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + methodHistory.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(methodHistory.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("CommitterName: " + methodHistory.getCommitterName()); + System.out.println("Before: " + methodHistory.getElementBefore().getName()); + System.out.println("After: " + methodHistory.getElementAfter().getName()); + + for (Change change : methodHistory.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + System.out.println("======================================================"); + } + +} diff --git a/src/test/java/org/codetracker/BlockTrackerImplTest.java b/src/test/java/org/codetracker/BlockTrackerImplTest.java new file mode 100644 index 00000000000..98fe3746d20 --- /dev/null +++ b/src/test/java/org/codetracker/BlockTrackerImplTest.java @@ -0,0 +1,118 @@ +package org.codetracker; + +import gr.uom.java.xmi.LocationInfo; +import org.codetracker.api.BlockTracker; +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.change.Change; +import org.codetracker.element.Block; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BlockTrackerImplTest { + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + @Test + public void ifToTernaryOperatorTest() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + BlockTracker blockTracker = CodeTracker.blockTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/blocktracking/ternary/Main.java") + .startCommitId("3b7a3dfdbc8c9a6233a7d631bc9ff1eb35bc0653") + .methodName("isPassed") + .methodDeclarationLineNumber(5) + .codeElementType(LocationInfo.CodeElementType.RETURN_STATEMENT) + .blockStartLineNumber(6) + .blockEndLineNumber(6) + .build(); + + History blockHistory = blockTracker.track(); + printHappyCaseOutput(blockHistory); + assertNotNull(blockHistory); + assertTrue(!blockHistory.getHistoryInfoList().isEmpty() && blockHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + @Test + public void testDelegateMethodLocalFile() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + BlockTracker blockTracker = CodeTracker.blockTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/blocktracking/delegate/Main.java") + .startCommitId("97eb547f6fae7c09aba90f030f0557a77ee86cdf") + .methodName("getTheYoungestEmployeeSalary") + .methodDeclarationLineNumber(12) + .codeElementType(LocationInfo.CodeElementType.ENHANCED_FOR_STATEMENT) + .blockStartLineNumber(15) + .blockEndLineNumber(17) + .build(); + + History blockHistory = blockTracker.track(); + printHappyCaseOutput(blockHistory); + assertNotNull(blockHistory); + assertTrue(!blockHistory.getHistoryInfoList().isEmpty() && blockHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + @Test + public void testDelegateSameSignatureMethodOtherFile() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + BlockTracker blockTracker = CodeTracker.blockTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/blocktracking/delegate/Utilitu.java") + .startCommitId("f99f42b46810963f9e27973a28169734c5ee2ce3") + .methodName("getTheYoungestEmployeeSalary") + .methodDeclarationLineNumber(6) + .codeElementType(LocationInfo.CodeElementType.ENHANCED_FOR_STATEMENT) + .blockStartLineNumber(8) + .blockEndLineNumber(10) + .build(); + + History blockHistory = blockTracker.track(); + printHappyCaseOutput(blockHistory); + assertNotNull(blockHistory); + assertTrue(!blockHistory.getHistoryInfoList().isEmpty() && blockHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + private void printHappyCaseOutput(History blockHistory){ + for (History.HistoryInfo historyInfo : blockHistory.getHistoryInfoList()) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + historyInfo.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("Before: " + historyInfo.getElementBefore().getName()); + System.out.println("After: " + historyInfo.getElementAfter().getName()); + + for (Change change : historyInfo.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + } + System.out.println("======================================================"); + } + +} +// System.out.println("---- Statements visible to CodeTracker ----"); +// for (AbstractStatement st : +// startMethod.getUmlOperation() +// .getBody() +// .getCompositeStatement() +// .getAllStatements()) { +// +// System.out.printf("%s %d-%d%n", +// st.getLocationInfo().getCodeElementType(), +// st.getLocationInfo().getStartLine(), +// st.getLocationInfo().getEndLine()); +// } +// System.out.println("-------------------------------------------"); + + diff --git a/src/test/java/org/codetracker/FalseRenameDetectionTests.java b/src/test/java/org/codetracker/FalseRenameDetectionTests.java new file mode 100644 index 00000000000..3aa64101f68 --- /dev/null +++ b/src/test/java/org/codetracker/FalseRenameDetectionTests.java @@ -0,0 +1,170 @@ +package org.codetracker; + +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.api.MethodTracker; +import org.codetracker.change.Change; +import org.codetracker.element.Method; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FalseRenameDetectionTests { + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + /*************************************************************************** + * ************************************* + * False Rename Detection Instead Of Extract Class & Move Method + * ************************************* + */ + @Test + public void breakRMReturnRenameWhenExtractClassNew() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/newclass/Calculator.java") + .startCommitId("8ef06dced725cca8cc22705d4eba95ef39ae1e36") + .methodName("print") + .methodDeclarationLineNumber(15) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + @Test + public void breakRMReturnRenameWhenExtractClassExtend() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/extend/Calculator.java") + .startCommitId("a14ddd9082a29b53a0fe4b153f65b777fe122931") + .methodName("print") + .methodDeclarationLineNumber(20) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + @Test + public void breakRMReturnRenameWhenExtractClassFieldInjection() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/autowired/Calculator.java") + .startCommitId("0eae1091dc5ce1eddbd1edd62dcb12936ebb1978") + .methodName("print") + .methodDeclarationLineNumber(18) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + + + @Test + public void breakRMReturnRenameWhenExtractClassConstructionInjection() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/constructor/Calculator.java") + .startCommitId("ebe0ba262dc9c92473336baeb4d1d71df77f7d92") + .methodName("print") + .methodDeclarationLineNumber(19) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + + @Test + public void breakRMReturnRenameWhenExtractClassSetterInjection() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/setter/Calculator.java") + .startCommitId("ea57744b29d0a8edf24348cf85db997f9192c12c") + .methodName("print") + .methodDeclarationLineNumber(20) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + @Test + public void returnRenameWhenExtractClassStaticMethod() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/staticmethod/DiscountUtil.java") + .startCommitId("33bf82563170a549f8366271055a43ee1a53e13d") + .methodName("calculateDiscount") + .methodDeclarationLineNumber(4) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + @Test + public void returnRenameWhenExtractClassFunctionalInterfaceSupplier() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/dependencyinjection/functionalinterface/Calculator.java") + .startCommitId("2df483b1cd01681f1cdc976ddc53d010b8e9cf23") + .methodName("sum") + .methodDeclarationLineNumber(7) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + + private void printHappyCaseOutput(History methodHistory){ + for (History.HistoryInfo historyInfo : methodHistory.getHistoryInfoList()) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + historyInfo.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("Before: " + historyInfo.getElementBefore().getName()); + System.out.println("After: " + historyInfo.getElementAfter().getName()); + + for (Change change : historyInfo.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + } + System.out.println("======================================================"); + } + +} diff --git a/src/test/java/org/codetracker/MethodTrackerImplTest.java b/src/test/java/org/codetracker/MethodTrackerImplTest.java new file mode 100644 index 00000000000..659e7872a77 --- /dev/null +++ b/src/test/java/org/codetracker/MethodTrackerImplTest.java @@ -0,0 +1,218 @@ +package org.codetracker; + + +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.api.MethodTracker; +import org.codetracker.change.Change; +import org.codetracker.element.Method; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MethodTrackerImplTest { + + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + + @Test + public void returnsHistoryOfRenameMethodGivenCommitInfoOfRepository() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/service/CryptoService.java") + .startCommitId("d0d9edcfb611ee35978938f7e35250f1ae982057") + .methodName("ceateUser") + .methodDeclarationLineNumber(43) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().size() > 2); + } + @Test + public void returnsHistoryOfMovedMethodContainerChanged() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/CryptographyApplication.java") + .startCommitId("8e0ada4854818a764d337d40c25f6060aa8ea1b2") + .methodName("main") + .methodDeclarationLineNumber(42) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + } + @Test + public void returnNoChangeForBodyChangeDueToCollision() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/CryptographyApplication.java") + .startCommitId("5c08104df4a48e253714226c0d9c0d0f4e40ee30") + .methodName("run") + .methodDeclarationLineNumber(47) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("body change")); + } + @Test + public void returnContainerChangeForMovedFile() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/dto/request/DecryptReqDto.java") + .startCommitId("213ed6bbd3c0b94423e7338b191e26f876c0c0d5") + .methodName("getBase64OfCipherTest") + .methodDeclarationLineNumber(17) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + + } +@Test +public void returnTheLastRefactoringTypeBeforeRenamingFile() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/dto/EncryptReqDto.java") + .startCommitId("213ed6bbd3c0b94423e7338b191e26f876c0c0d5") + .methodName("getPlainText") + .methodDeclarationLineNumber(6) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + +} + @Test + public void returnContainerChangeAfterRenamingFile() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/dto/EncryptRequestDto.java") + .startCommitId("f8b244f015b79c95dfb7fb86340c749447f61b34") + .methodName("getPlainText") + .methodDeclarationLineNumber(6) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + + } + @Test + public void testMoveFileAndBodyChangeSimultaneously() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/dto/Response/EncryptResDto.java") + .startCommitId("d64f222f3512c8ce5453d53c77093ae4b2a995ca") + .methodName("getCipherText") + .methodDeclarationLineNumber(6) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + } + @Test + public void testConstructorWithMinimalChangeCommit() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/dto/UserDto.java") + .startCommitId("d64f222f3512c8ce5453d53c77093ae4b2a995ca") + .methodName("UserDto") + .methodDeclarationLineNumber(9) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + + } + @Test + public void testMethodClassImplementsInterface() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/config/CustomUserDetailManagerImpl.java") + .startCommitId("d64f222f3512c8ce5453d53c77093ae4b2a995ca") + .methodName("createUser") + .methodDeclarationLineNumber(22) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(1).getChangeType().getTitle().equals("container change")); + } + @Test + public void uncommentedMethod() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + MethodTracker methodTracker = CodeTracker.methodTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/comment_to_method/Main.java") + .startCommitId("f1860ea8ac8f61b539b83236e6b7ca020e069cdb") + .methodName("goodbye") + .methodDeclarationLineNumber(7) + .build(); + History methodHistory = methodTracker.track(); + printHappyCaseOutput(methodHistory); + assertNotNull(methodHistory); + assertTrue(!methodHistory.getHistoryInfoList().isEmpty() && methodHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + private void printHappyCaseOutput(History methodHistory){ + for (History.HistoryInfo historyInfo : methodHistory.getHistoryInfoList()) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + historyInfo.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("CommitterName: " + historyInfo.getCommitterName()); + + System.out.println("Before: " + historyInfo.getElementBefore().getName()); + System.out.println("After: " + historyInfo.getElementAfter().getName()); + + for (Change change : historyInfo.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + } + System.out.println("======================================================"); + } + +} diff --git a/src/test/java/org/codetracker/VariableTrackerImplTest.java b/src/test/java/org/codetracker/VariableTrackerImplTest.java new file mode 100644 index 00000000000..3628d2bba85 --- /dev/null +++ b/src/test/java/org/codetracker/VariableTrackerImplTest.java @@ -0,0 +1,101 @@ +package org.codetracker; + +import org.codetracker.api.CodeTracker; +import org.codetracker.api.History; +import org.codetracker.api.VariableTracker; +import org.codetracker.change.Change; +import org.codetracker.element.Variable; +import org.eclipse.jgit.lib.Repository; +import org.junit.jupiter.api.Test; +import org.refactoringminer.api.GitService; +import org.refactoringminer.util.GitServiceImpl; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class VariableTrackerImplTest { + String FOLDER_TO_CLONE = "D:\\work\\programming\\CodeTrackerTesting"; + String GITHUB_REPO_TO_CLONE = "https://github.com/parinaz-st/CryptographyRestService.git"; + @Test + public void testSimpleVariableTracker() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + + VariableTracker variableTracker = CodeTracker.variableTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/variabletracking/Main.java") + .startCommitId("6ad3db2a40834eba62b82c36aa07ab7e01c469d7") + .methodName("calculate") + .methodDeclarationLineNumber(5) + .variableName("num") + .variableDeclarationLineNumber(6) + .build(); + History variableHistory = variableTracker.track(); + printHappyCaseOutput(variableHistory); + assertNotNull(variableHistory); + assertTrue(!variableHistory.getHistoryInfoList().isEmpty() && variableHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + } + @Test + public void returnMultiVariableDeclarationRefactoring() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + + VariableTracker variableTracker = CodeTracker.variableTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/multiVariableDeclaration/Main.java") + .startCommitId("5bcc51064d77c323f4422009e66e2c6de93c86f1") + .methodName("main") + .methodDeclarationLineNumber(6) + .variableName("n") + .variableDeclarationLineNumber(8) + .build(); + History variableHistory = variableTracker.track(); + printHappyCaseOutput(variableHistory); + assertNotNull(variableHistory); + assertTrue(!variableHistory.getHistoryInfoList().isEmpty() && variableHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + @Test + public void returnMultiVariableDeclarationSlideStatementRefactoring() throws Exception { + GitService gitService = new GitServiceImpl(); + Repository repository = gitService.cloneIfNotExists(FOLDER_TO_CLONE, + GITHUB_REPO_TO_CLONE); + + VariableTracker variableTracker = CodeTracker.variableTracker() + .repository(repository) + .filePath("CryptoServer/src/main/java/com/cryptography/codetrackertest/multiVariableDeclaration/SlideStatement.java") + .startCommitId("b7a6cdde69b3af5247a1289ce34a3b5e5cff4593") + .methodName("main") + .methodDeclarationLineNumber(6) + .variableName("n") + .variableDeclarationLineNumber(9) + .build(); + History variableHistory = variableTracker.track(); + printHappyCaseOutput(variableHistory); + assertNotNull(variableHistory); + assertTrue(!variableHistory.getHistoryInfoList().isEmpty() && variableHistory.getHistoryInfoList().get(0).getChangeType().getTitle().equals("introduced")); + + } + public void printHappyCaseOutput(History variableHistory){ + for (History.HistoryInfo historyInfo : variableHistory.getHistoryInfoList()) { + System.out.println("======================================================"); + System.out.println("Commit ID: " + historyInfo.getCommitId()); + System.out.println("Date: " + + LocalDateTime.ofEpochSecond(historyInfo.getCommitTime(), 0, ZoneOffset.UTC)); + System.out.println("Before: " + historyInfo.getElementBefore().getName()); + System.out.println("After: " + historyInfo.getElementAfter().getName()); + + for (Change change : historyInfo.getChangeList()) { + System.out.println(change.getType().getTitle() + ": " + change); + } + } + System.out.println("======================================================"); + + } + +}