This project aims to introduce CodeTracker, a refactoring-aware tool that can generate the commit change history for method and variable declarations in a Java project with a very high accuracy.
- How to Build
- How to add as a Maven dependency
- How to Track Methods
- How to Track Variables
- How to Track Attributes
- Oracle
- Experiments
To build this project you need to have Maven.
Run mvn install
in the root folder of CodeTracker.
To add code-tracker as a maven dependency in your project, add the following dependency:
<dependency>
<groupId>org.codetracker</groupId>
<artifactId>code-tracker</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
CodeTracker can track the history of methods in git repositories.
In the code snippet below we demonstrate how to print all changes performed in the history of public void fireErrors(String fileName, SortedSet<LocalizedMessage> errors)
.
GitService gitService = new GitServiceImpl();
try (Repository repository = gitService.cloneIfNotExists("tmp/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<Method> methodHistory = methodTracker.track();
for (History.HistoryInfo<Method> 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("======================================================");
}
CodeTracker can track the history of variables in git repositories.
In the code snippet below we demonstrate how to print all changes performed in the history of final String stripped
.
GitService gitService = new GitServiceImpl();
try (Repository repository = gitService.cloneIfNotExists("tmp/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<Variable> variableHistory = variableTracker.track();
for (History.HistoryInfo<Variable> 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("======================================================");
}
CodeTracker can track the history of attributes in git repositories.
In the code snippet below we demonstrate how to print all changes performed in the history of private PropertyCacheFile cacheFile
.
GitService gitService = new GitServiceImpl();
try (Repository repository = gitService.cloneIfNotExists("tmp/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<Attribute> attributeHistory = attributeTracker.track();
for (History.HistoryInfo<Attribute> 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("======================================================");
}
The oracle we used to evaluate CodeTracker is an extension of CodeShovel oracle, including the evolution history of 200 methods and the evolution history of 1346 variables declared in these methods, is available here or in the following links:
In the extended oracle we fixed all inaccuracies that we found in the original oracle. For example, the following methods in the original oracle are erroneously matched with another method which is extracted from their body. In fact, these methods are introduced as a result of an Extract Method refactoring.
- Training
- checkstyle-CommonUtils-createPattern
- checkstyle-WhitespaceAroundCheck-shouldCheckSeparationFromNextToken
- checkstyle-WhitespaceAroundCheck-isNotRelevantSituation
- commons-lang-EqualsBuilder-reflectionAppend
- commons-lang-RandomStringUtils-random
- commons-lang-NumberUtils-isCreatable
- flink-FileSystem-getUnguardedFileSystem
- flink-RemoteStreamEnvironment-executeRemotely
- hibernate-orm-SimpleValue-buildAttributeConverterTypeAdapter
- javaparser-MethodResolutionLogic-isApplicable
- javaparser-Difference-applyRemovedDiffElement
- javaparser-JavaParserFacade-getTypeConcrete
- jgit-IndexDiff-diff
- jgit-UploadPack-sendPack
- junit4-ParentRunner-applyValidators
- junit5-TestMethodTestDescriptor-invokeTestMethod
- junit5-DefaultLauncher-discoverRoot
- okhttp-Http2Connection-newStream
- Test
- commons-io-IOUtils-toInputStream
- commons-io-FilenameUtils-wildcardMatch
- hadoop-SchedulerApplicationAttempt-resetSchedulingOpportunities
- hibernate-search-ClassLoaderHelper-instanceFromName
- spring-boot-DefaultErrorAttributes-addErrorMessage
- lucene-solr-QueryParserBase-addClause
- intellij-community-ModuleCompileScope-isUrlUnderRoot
- intellij-community-TranslatingCompilerFilesMonitor-isInContentOfOpenedProject
- mockito-MatchersBinder-bindMatchers
To avoid unnecessary processing and speed up the tracking process, CodeTracker excludes some files from the source code model. The excluding action may cause misreporting of change type in some special scenarios. Although CodeTracker supports three scenarios in which additional files need to be included in the source code model, it may misreport MoveMethod changes as FileMove because the child commit model did not include the origin file of the method. In the test oracle, there are three such cases: case 1, case 2 and case 3.
As part of our experiments, we measured the execution time of CodeTracker and CodeShovel to track each method's change history in the training and testing sets. All data we recorded for this experiment and the script for generating the execution time plots are available here.
All data we collect to compute the precision and recall of CodeTracker and CodeShovel at commit level and change level are available in the following links: