Skip to content

Commit

Permalink
add catch/finally change type detection
Browse files Browse the repository at this point in the history
  • Loading branch information
flozender committed Mar 2, 2023
1 parent 6d85999 commit dccff2f
Showing 1 changed file with 97 additions and 16 deletions.
113 changes: 97 additions & 16 deletions src/main/java/org/codetracker/BlockTrackerGumTreeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,16 @@ public History<Block> track() throws Exception {

Map<String, CodeElementType> treeToBlockType = Map.ofEntries(
entry("ForStatement", CodeElementType.FOR_STATEMENT),
entry("EnhancedForStatement", CodeElementType.ENHANCED_FOR_STATEMENT),
entry("WhileStatement", CodeElementType.WHILE_STATEMENT),
entry("DoStatement", CodeElementType.DO_STATEMENT),
entry("TryStatement", CodeElementType.TRY_STATEMENT),
entry("IfStatement", CodeElementType.IF_STATEMENT)
entry("IfStatement", CodeElementType.IF_STATEMENT),
entry("CatchClause", CodeElementType.CATCH_CLAUSE),
entry("SwitchStatement", CodeElementType.SWITCH_STATEMENT),
entry("SynchronizedStatement", CodeElementType.SYNCHRONIZED_STATEMENT)
);


// The method exists but the block doesn't, so it's newly introduced
if (leftBlockGT == null) {
Block blockBefore = Block.of(rightBlock.getComposite(), rightBlock.getOperation(), parentVersion);
Expand All @@ -305,33 +310,79 @@ public History<Block> track() throws Exception {

boolean bodyChange = false;
boolean expressionChange = false;
boolean catchClauseChange = false;
boolean finallyBlockChange = false;

for (Action action : actions.asList()) {
// Here check each action and derive the change made
CodeElementRange actionRange = new CodeElementRange(action.getNode(), lrSource);
CodeElementRange blockRange = new CodeElementRange(rightBlockGT, lrSource);

if (actionRange.startLine <= blockRange.endLine
&& actionRange.endLine >= blockRange.startLine) {
if (actionOverlapsElement(actionRange, blockRange, true)) {

Tree expression = null;
Tree body = null;
ArrayList<Tree> catchClauses = new ArrayList<>();
Tree finallyBlock = null;

for (Tree parent: action.getNode().getParents()){
System.out.println("Parent type " + parent.getType().toString());
if (startLine(parent, lrSource) == blockRange.startLine && parent.getType().toString().contains("Expression")){
expression = parent;
CodeElementRange parentRange = new CodeElementRange(parent, lrSource);
System.out.println("Parent type " + parent.getType().toString() + " - " + parentRange.startLine + ", " + parentRange.endLine);
// if the action parent start line matches our block's start line
// we have our element
if (parentRange.startLine == blockRange.startLine &&
(parent.getType().toString().contains("Statement") ||
parent.getType().toString().equals("CatchClause"))) {

// obtain statement body, expression, and catch/finally positions (if any)
System.out.println("Children: " + parent.getChildren());
for (Tree child: parent.getChildren()){
String childType = child.getType().toString();
switch (childType) {
case "InstanceofExpression":
expression = child;
break;
case "Block":
if (body == null){
body = child;
} else {
finallyBlock = child;
}
break;
case "CatchClause":
catchClauses.add(child);
break;
}
}
}
}

CodeElementRange bodyRange = new CodeElementRange(body, lrSource);
CodeElementRange expressionRange = new CodeElementRange(expression, lrSource);
CodeElementRange catchClauseRange = new CodeElementRange(catchClauses, lrSource);
CodeElementRange finallyBlockRange = new CodeElementRange(finallyBlock, lrSource);

// check if a change was made within an expression
if (actionRange.startPosition <= expressionRange.endPosition && actionRange.endPosition >= expressionRange.startPosition){
if (actionOverlapsElement(actionRange, expressionRange)){
expressionChange = true;
}
// check if a change was made within the body
if (actionRange.endPosition > expressionRange.endPosition){
if (actionOverlapsElement(actionRange, bodyRange)){
bodyChange = true;
}
// if both types of changes are found, break loop
if (bodyChange && expressionChange){
// check if a change was made within a 'catch' clause
if (actionOverlapsElement(actionRange, catchClauseRange)){
catchClauseChange = true;
}

// check if a change was made within the 'finally' clause
if (actionOverlapsElement(actionRange, finallyBlockRange)){
finallyBlockChange = true;
}

// if all types of changes are found, break loop
// && catchClauseChange
if (bodyChange && expressionChange && catchClauseChange && finallyBlockChange){
break;
}
}
Expand All @@ -345,7 +396,15 @@ public History<Block> track() throws Exception {
blockChangeHistory.addChange(leftBlock, rightBlock, ChangeFactory.forBlock(Change.Type.BODY_CHANGE));
}

if (!bodyChange && !expressionChange) {
if (catchClauseChange){
blockChangeHistory.addChange(leftBlock, rightBlock, ChangeFactory.forBlock(Change.Type.CATCH_BLOCK_CHANGE));
}

if (finallyBlockChange){
blockChangeHistory.addChange(leftBlock, rightBlock, ChangeFactory.forBlock(Change.Type.FINALLY_BLOCK_CHANGE));
}

if (!bodyChange && !expressionChange && !catchClauseChange && !finallyBlockChange) {
blockChangeHistory.addChange(leftBlock, rightBlock, ChangeFactory.of(AbstractChange.Type.NO_CHANGE));
}

Expand Down Expand Up @@ -381,10 +440,10 @@ public GumTreeSource(Repository repository, String commitId, String filePath) {
}

public class CodeElementRange {
int startLine = -1;
int endLine = -1;
int startPosition = -1;
int endPosition = -1;
public int startLine = -1;
public int endLine = -1;
public int startPosition = -1;
public int endPosition = -1;

public CodeElementRange(Tree codeElement, LineReader lr){
if (codeElement == null) {
Expand All @@ -395,6 +454,28 @@ public CodeElementRange(Tree codeElement, LineReader lr){
this.startLine = startLine(codeElement, lr);
this.endLine = endLine(codeElement, lr);
}

public CodeElementRange(ArrayList<Tree> codeElements, LineReader lr){
if (codeElements == null || codeElements.size() == 0) {
return;
}
int startPosition = Integer.MAX_VALUE;
int endPosition = 0;

for (Tree codeElement : codeElements){
startPosition = Math.min(startPosition, codeElement.getPos());
endPosition = Math.max(endPosition, codeElement.getEndPos());
}
this.startPosition = startPosition;
this.endPosition = endPosition;
this.startLine = startLine(this.startPosition, lr);
this.endLine = endLine(this.endPosition, lr);
}

@Override
public String toString() {
return "Lines: (" + startLine + ", " + endLine + "), Positions: (" + startPosition + ", " + endPosition + ")";
}
}

}

0 comments on commit dccff2f

Please sign in to comment.