public class AssignmentTransformer extends AbstractTransformer implements AliasHandler, AssignmentHandler, ClassHandler, CrossAnalysisHandler, FieldDeclarationHandler, MethodDeclarationHandler
In this approach, each assignment to a state variable is
refactored to become a method call, which, before actually assigning
the new value, back up the old value of the field in a record (see
FieldRecord
).
This transformer implements several handlers. It does the refactoring as the
type analyzer (TypeAnalyzer
) analyzes the original source code. The
analyzer calls back methods defined in the handlers after assigning
appropriate types to AST nodes. Those callback methods (implemented in this
class) refactors the given nodes on-the-fly as the type analysis goes on.
This class must be used at the same time as ConstructorTransformer
to get the correct refactoring result.
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
COMMIT_NAME
The name of commit methods.
|
static boolean |
HANDLE_STATIC_FIELDS
Whether to refactor private static fields.
|
static boolean |
OPTIMIZE_CALL
Whether to optimize method calls.
|
static java.lang.String |
PROXY_NAME
The name of the proxy class created in each anonymous class.
|
static java.lang.String |
RECORD_PREFIX
The prefix of records (new fields to be added to a class).
|
static java.lang.String |
RECORDS_NAME
The name of the record array.
|
static java.lang.String |
RESTORE_NAME
The name of restore methods.
|
ASSIGN_PREFIX, BACKUP_PREFIX, CHECKPOINT_NAME, CHECKPOINT_RECORD_NAME, GET_CHECKPOINT_NAME, SET_CHECKPOINT_NAME
Constructor and Description |
---|
AssignmentTransformer() |
Modifier and Type | Method and Description |
---|---|
void |
enter(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node,
TypeAnalyzerState state)
Enter an anonymous class declaration.
|
void |
enter(org.eclipse.jdt.core.dom.FieldDeclaration node,
TypeAnalyzerState state)
Enter a field declaration.
|
void |
enter(org.eclipse.jdt.core.dom.MethodDeclaration node,
TypeAnalyzerState state)
Enter a method declaration.
|
void |
enter(org.eclipse.jdt.core.dom.TypeDeclaration node,
TypeAnalyzerState state)
Enter an class declaration.
|
void |
exit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node,
TypeAnalyzerState state)
Exit an anonymous class declaration, and add extra methods and fields
to it.
|
void |
exit(org.eclipse.jdt.core.dom.FieldDeclaration node,
TypeAnalyzerState state)
Exit a field declaration.
|
void |
exit(org.eclipse.jdt.core.dom.MethodDeclaration node,
TypeAnalyzerState state)
Exit a method declaration.
|
void |
exit(org.eclipse.jdt.core.dom.TypeDeclaration node,
TypeAnalyzerState state)
Exit a class declaration, and add extra methods and fields to it.
|
void |
handle(org.eclipse.jdt.core.dom.Assignment node,
TypeAnalyzerState state)
Handle an assignment, and refactor it to be a special method call if the
left-hand side of the assignment is a state variable.
|
void |
handle(org.eclipse.jdt.core.dom.ClassInstanceCreation node,
TypeAnalyzerState state)
Handle a class instance creation.
|
void |
handle(org.eclipse.jdt.core.dom.MethodInvocation node,
TypeAnalyzerState state)
Handle a method invocation.
|
void |
handle(org.eclipse.jdt.core.dom.PostfixExpression node,
TypeAnalyzerState state)
Handle a postfix expression, and refactor it to be a special method
call if its subexpression evaluates to be a state variable.
|
void |
handle(org.eclipse.jdt.core.dom.PrefixExpression node,
TypeAnalyzerState state)
Handle a prefix expression, and refactor it to be a special method
call if its subexpression evaluates to be a state variable.
|
void |
handle(org.eclipse.jdt.core.dom.ReturnStatement node,
TypeAnalyzerState state)
Handle a return statement.
|
void |
handle(TypeAnalyzerState state)
Fix the refactoring result when the set of cross-analyzed types
changes.
|
void |
handle(org.eclipse.jdt.core.dom.VariableDeclarationFragment node,
TypeAnalyzerState state)
Handle a variable declaration fragment.
|
_getAssignMethodName, _getBackupMethodName, addToLists, createName, createType, getClassName, getClassName, hasMethod, hasMethod, indexOf, isFieldDuplicated, lastIndexOf, removeNode, replaceNode
public static final java.lang.String COMMIT_NAME
public static final boolean HANDLE_STATIC_FIELDS
public static final boolean OPTIMIZE_CALL
public static final java.lang.String PROXY_NAME
public static final java.lang.String RECORDS_NAME
public static final java.lang.String RECORD_PREFIX
public static final java.lang.String RESTORE_NAME
public void enter(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node, TypeAnalyzerState state)
enter
in interface ClassHandler
node
- The AST node of the anonymous class declaration.state
- The current state of the type analyzer.public void enter(org.eclipse.jdt.core.dom.FieldDeclaration node, TypeAnalyzerState state)
enter
in interface FieldDeclarationHandler
node
- The AST node of the field declaration.state
- The current state of the type analyzer.public void enter(org.eclipse.jdt.core.dom.MethodDeclaration node, TypeAnalyzerState state)
enter
in interface MethodDeclarationHandler
node
- The AST node of the method declaration.state
- The current state of the type analyzer.public void enter(org.eclipse.jdt.core.dom.TypeDeclaration node, TypeAnalyzerState state)
enter
in interface ClassHandler
node
- The AST node of the anonymous class declaration.state
- The current state of the type analyzer.public void exit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node, TypeAnalyzerState state)
This function is called after all the existing methods and fields in
the same class has been visited, and all the field assignments in it
are handled with handle(Assignment, TypeAnalyzerState)
.
exit
in interface ClassHandler
node
- The AST node of the anonymous class declaration.state
- The current state of the type analyzer.public void exit(org.eclipse.jdt.core.dom.FieldDeclaration node, TypeAnalyzerState state)
exit
in interface FieldDeclarationHandler
node
- The AST node of the field declaration.state
- The current state of the type analyzer.public void exit(org.eclipse.jdt.core.dom.MethodDeclaration node, TypeAnalyzerState state)
exit
in interface MethodDeclarationHandler
node
- The AST node of the method declaration.state
- The current state of the type analyzer.public void exit(org.eclipse.jdt.core.dom.TypeDeclaration node, TypeAnalyzerState state)
This function is called after all the existing methods and fields in
the same class has been visited, and all the field assignments in it
are handled with handle(Assignment, TypeAnalyzerState)
.
exit
in interface ClassHandler
node
- The AST node of the anonymous class declaration.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.Assignment node, TypeAnalyzerState state)
An assignment may also be an alias point, in which case an array field is aliased with a local variable. For example: Suppose field is an array field recognized as a state variable. Expression buffer = field aliases the field with a local variable buffer. After that, the method may modify the field array (with the name buffer) without letting field's owner class know. So, this is an alias point. This function refactors this alias point and replaces field with a function call.
handle
in interface AliasHandler
handle
in interface AssignmentHandler
node
- The assignment to be refactored.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.ClassInstanceCreation node, TypeAnalyzerState state)
For example: Suppose field is an array field recognized as a state variable. Expression new MyClass(field) instantiates an object of class MyClass with argument field. The constructor of MyClass may modify the field array without letting field's owner class know. So, this is an alias point. This function refactors this alias point and replaces field with a function call.
handle
in interface AliasHandler
node
- The class instance creation to be refactored.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.MethodInvocation node, TypeAnalyzerState state)
For example: Suppose field is an array field recognized as a state variable. Expression func(field) invokes method func an with argument field. func may modify the field array in its body without letting field's owner class know. So, this is an alias point. This function refactors this alias point and replaces field with a function call.
handle
in interface AliasHandler
node
- The method invocation to be refactored.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.PostfixExpression node, TypeAnalyzerState state)
handle
in interface AssignmentHandler
node
- The postfix expression to be refactored.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.PrefixExpression node, TypeAnalyzerState state)
handle
in interface AssignmentHandler
node
- The prefix expression to be refactored.state
- The current state of the type analyzer.public void handle(org.eclipse.jdt.core.dom.ReturnStatement node, TypeAnalyzerState state)
For example: Suppose field is an array field recognized as a state variable. Statement return field; returns the field to the calling method. The calling method may modify the field array in its body without letting field's owner class know. So, this is an alias point. This function refactors this alias point and replaces field with a function call.
handle
in interface AliasHandler
node
- The return statement to be refactored.state
- The current state of the type analyzer.public void handle(TypeAnalyzerState state)
The set of cross-analyzed types defines the growing set of types that are analyzed in a run. Special care is taken for cross-analyzed types because they are monitored by checkpoint objects, and checkpoint-related extra methods are added to them. Unfortunately, it is not possible to know all the cross-analyzed types at the beginning. It is then necessary to fix the refactoring result when more cross-analyzed types are discovered later.
handle
in interface CrossAnalysisHandler
state
- The current state of the type analyzer.TypeAnalyzerState.getCrossAnalyzedTypes()
public void handle(org.eclipse.jdt.core.dom.VariableDeclarationFragment node, TypeAnalyzerState state)
For example: Suppose field is an array field recognized as a state variable. Variable declaration int[] buffer = field (with one fragment only) aliases the field to with name buffer. The declaring method may modify the field array (with name buffer) in its body without letting field's owner class know. So, this is an alias point. This function refactors this alias point and replaces field with a function call.
handle
in interface AliasHandler
node
- The variable declaration fragment to be refactored.state
- The current state of the type analyzer.