I would like to write a transformation to move a field from one
typeDeclaration to another. Its no problem to erase a field from one type
declaration. However, im struggeling to add the field in another
typeDeclaration. See the code snippet for current attempt below. Based on the
transformation tutorial i would need a statementBlock to attach the field.
unfortunately, im not able to retrieve a StatementBlock from the available
TypeDeclaration to attach the field.
Maybe someone can give a hint how to solve this issue.
private void addField(TypeDeclaration targetTypeDeclaration, Field field)
{
List<Field> allFields = targetTypeDeclaration.getAllFields();
allFields.add(field); // certainly this doesnt write back into the definition
of the typeDeclaration.
CrossReferenceServiceConfiguration crsc =
CrossReferenceServiceConfigurationFactory.getInstance();
ChangeHistory changeHistory = crsc.getChangeHistory();
ProgramElement pElement = (ProgramElement) field;
changeHistory.attached(pElement);
}
regards
Frederik
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There are two issues:
1) A "field" is never attached to a StatementBlock, but to a TypeDeclaration.
Only "local variables" can be attached to statement blocks.
2) There's an essential difference between a general "Field" and a
"FieldDeclaration" (this generailizes to other members as well). A "Field"
can, e.g., also be a "FieldInfo" as retrieved from bytecode; recoder does not
refactor bytecode. A "FieldDeclaration" is a field that is present in the AST,
i.e., in the analyzed source code.
Now, "getAllFields()" also returns a List also including inherited fields.
What you are looking for is "getFields()", which returns an ASTList. An
ASTList is part of the AST; changes to it are reflected in the AST.
What you probably are looking for is this (warning: untested, I leave that to
you :))
private void addField(TypeDeclaration targetTypeDeclaration, Field field) {
ASTList<Field> fields = targetTypeDeclaration.getFields();
fields.add(targetTypeDeclaration.getProgramFactory().createFieldDeclaration(..
.);
// rest as you wrote it...
}
You will have to provide proper arguments to createFieldDeclaration(). The
following constructor should be present (again, I didn't test it as I don't
have recoder at hand right now):
pf.createFieldDeclaration(TypeKit.createTypeReference(field.getType()),
field.getName());
Let me know if you have any further questions.
Best regards,
Tobias
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
thanks for your help... Below a code snipped including your hints, which
enabled me to move a field to a given type declaration. Its certainly not
perfect, but for now it does the job:-) Thanks again
If you somehow can guarantee that a FieldDeclaration has only one
FieldSpecification, it can be done much easier because you can just move/clone
the FieldDeclaration (examples for a FieldDeclaration with two
FieldSpecifications: int a, b; -- it makes source code transformations in
general much more complicated...):
In this case you can just deepClone() the FieldDeclaration (note: it's
always better to deepClone() than reusing an AST object, for defensive
programming reasons...)
TypeDeclaration from = ...;
TypeDeclaration to = ...;
FieldDeclaration fd = ...;
FieldDeclaration replFd = fd.deepClone();
int idx = from.getChildPositionCode(fd);
from.replaceChild(fd, null);
to.getMemberDeclarations().add(replFD);
to.makeRoleValid();
sc.getChangeHistory().detached(fd, idx);
sc.getChangeHistory().attached(replFD);
(Again, I haven't actually executed the code above...)
Best regards,
Tobias
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi recoder developers,
I would like to write a transformation to move a field from one
typeDeclaration to another. Its no problem to erase a field from one type
declaration. However, im struggeling to add the field in another
typeDeclaration. See the code snippet for current attempt below. Based on the
transformation tutorial i would need a statementBlock to attach the field.
unfortunately, im not able to retrieve a StatementBlock from the available
TypeDeclaration to attach the field.
Maybe someone can give a hint how to solve this issue.
private void addField(TypeDeclaration targetTypeDeclaration, Field field)
{
List<Field> allFields = targetTypeDeclaration.getAllFields();
allFields.add(field); // certainly this doesnt write back into the definition
of the typeDeclaration.
CrossReferenceServiceConfiguration crsc =
CrossReferenceServiceConfigurationFactory.getInstance();
ChangeHistory changeHistory = crsc.getChangeHistory();
ProgramElement pElement = (ProgramElement) field;
changeHistory.attached(pElement);
}
regards
Frederik
Hi,
There are two issues:
1) A "field" is never attached to a StatementBlock, but to a TypeDeclaration.
Only "local variables" can be attached to statement blocks.
2) There's an essential difference between a general "Field" and a
"FieldDeclaration" (this generailizes to other members as well). A "Field"
can, e.g., also be a "FieldInfo" as retrieved from bytecode; recoder does not
refactor bytecode. A "FieldDeclaration" is a field that is present in the AST,
i.e., in the analyzed source code.
Now, "getAllFields()" also returns a List also including inherited fields.
What you are looking for is "getFields()", which returns an ASTList. An
ASTList is part of the AST; changes to it are reflected in the AST.
What you probably are looking for is this (warning: untested, I leave that to
you :))
private void addField(TypeDeclaration targetTypeDeclaration, Field field) {
ASTList<Field> fields = targetTypeDeclaration.getFields();
fields.add(targetTypeDeclaration.getProgramFactory().createFieldDeclaration(..
.);
// rest as you wrote it...
}
You will have to provide proper arguments to createFieldDeclaration(). The
following constructor should be present (again, I didn't test it as I don't
have recoder at hand right now):
pf.createFieldDeclaration(TypeKit.createTypeReference(field.getType()),
field.getName());
Let me know if you have any further questions.
Best regards,
Tobias
Hi Tobias,
thanks for your help... Below a code snipped including your hints, which
enabled me to move a field to a given type declaration. Its certainly not
perfect, but for now it does the job:-) Thanks again
cheers
frederik
private void addFieldToTypeDeclaration(TypeDeclaration targetTypeDeclaration,
Field field)
{
FieldSpecification fieldSpecification = (FieldSpecification) field;
ASTList<DeclarationSpecifier> declarationSpecifiers =
fieldSpecification.getDeclarationSpecifiers();
JavaProgramFactory factory = targetTypeDeclaration.getFactory();
FieldDeclaration parent = fieldSpecification.getParent();
TypeReference typeReference = parent.getTypeReference();
FieldDeclaration fieldDeclaration = factory.createFieldDeclaration();
fieldDeclaration.setDeclarationSpecifiers(declarationSpecifiers);
fieldDeclaration.setFactory(factory);
fieldDeclaration.setMemberParent(targetTypeDeclaration);
fieldDeclaration.setTypeReference(typeReference);
ASTArrayList<FieldSpecification> fieldSpecifications = new
ASTArrayList<FieldSpecification>();
fieldSpecification.setParent(fieldDeclaration);
fieldSpecifications.add(fieldSpecification);
fieldDeclaration.setFieldSpecifications(fieldSpecifications);
ASTList<MemberDeclaration> members = targetTypeDeclaration.getMembers();
members.add(0, fieldDeclaration);
CrossReferenceServiceConfiguration crsc =
CrossReferenceServiceConfigurationFactory.getInstance();
ChangeHistory changeHistory = crsc.getChangeHistory();
ProgramElement pElement = (ProgramElement) fieldDeclaration;
changeHistory.attached(fieldSpecification);
changeHistory.attached(pElement);
}
Hi,
If you somehow can guarantee that a FieldDeclaration has only one
FieldSpecification, it can be done much easier because you can just move/clone
the FieldDeclaration (examples for a FieldDeclaration with two
FieldSpecifications: int a, b; -- it makes source code transformations in
general much more complicated...):
In this case you can just deepClone() the FieldDeclaration (note: it's
always better to deepClone() than reusing an AST object, for defensive
programming reasons...)
TypeDeclaration from = ...;
TypeDeclaration to = ...;
FieldDeclaration fd = ...;
FieldDeclaration replFd = fd.deepClone();
int idx = from.getChildPositionCode(fd);
from.replaceChild(fd, null);
to.getMemberDeclarations().add(replFD);
to.makeRoleValid();
sc.getChangeHistory().detached(fd, idx);
sc.getChangeHistory().attached(replFD);
(Again, I haven't actually executed the code above...)
Best regards,
Tobias