Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: All RoleHandlers supports set/add/remove #1793

Merged
merged 5 commits into from
Jan 8, 2018

Conversation

pvojtechovsky
Copy link
Collaborator

The list returned by RoleHandler#asList(CtElement) supports

  • set(int, Object)
  • remove(int)

for all kinds of roles.

The single value roles can use RoleHandler#asList(CtElement) too and you can call

  • set(0, value)
  • get(0)
  • add(value) - if previous value was null
  • remove(value) - to set the value to null

@@ -134,8 +139,64 @@ public ContainerKind getContainerKind() {
return asList(element);
};

public <W, X> java.util.List<X> asList(W element) {
return Collections.<X>singletonList(getValue(element));
public <W, X> java.util.List<X> asList(W e) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's already a lot of mixed responsibilities in this file and adding a new anonymous class here increases the complexity. So I'm ok with your changes but I'm in favor of extracting the static classes from this file to put them in their own file: I think it will help the future maintaining. WDYT?

@pvojtechovsky
Copy link
Collaborator Author

I'm in favor of extracting the static classes from this file to put them in their own file: I think it will help the future maintaining. WDYT?

Good idea. I am done with that. It is ready for merge.

assertEquals("some.test.package", oldValue.getQualifiedName());
assertEquals(0, packages.size());
assertNull(typeRef.getPackage());
//contract: get(0) can be called even on empty collection, because there is no way how to distinguish how that happened. Whether by remove(x) or by set(0, null)
Copy link
Collaborator

@surli surli Jan 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this contract odd: it's not the expected behaviour regarding Java standard usage of lists. Couldn't you check the size of the list? In this case what isEmpty() would return?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a normal List, it is wrapper around single value. The problem is
List list=...wrapperAroundSingleValue_x

x = "A"
assertEquals("A", list.get(0))
The problem is that both list operations
list.set(0, null);
list.remove(0);
causes the same result x=null
assertEquals(null, x)
assertEquals(0, list.size())

I have not found better way how to wrap single value as List. In all cases there is some little cosmetic inconsistency, because List has more internal state then single value ...

What do you suggest?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you suggest?

I was thinking about just calling a check on the get method when you return the AbstractList: you could just check the size of the list and if it's empty you always return an IndexOutOfBoundException.

@pvojtechovsky
Copy link
Collaborator Author

if it's empty you always return an IndexOutOfBoundException.

then this code will throw IndexOutOfBoundException.
list.set(0, null);
list.get(0) -> throws IndexOutOfBoundException.

current implementation passes this:
assertSame(null, list.get(0))

May be I might add an extra internal state into ListWrapper, which would distinguish between
A) list has one null value
B) list has no value
Then the List would behave consistent

@INRIA INRIA deleted a comment from spoon-bot Jan 5, 2018
@pvojtechovsky
Copy link
Collaborator Author

I am done here.

There are still some "inconsistencies" to standard List behavior, but they were intentional.

add(x) into collection which contains x, keeps size on 1 - so it behaves like a Set
add(null) into collection which contains x, keeps size on 1 - instead of throwing "Too many elements. Max size is 1"
add(null) into empty collection keeps value on null, but sets size on 1

WDYT? Should we make it List compatible or say it is intentional?

@monperrus
Copy link
Collaborator

I like the Least Astonishment Principle, so I would go for being List-compatible.

@pvojtechovsky
Copy link
Collaborator Author

It should be list compatible now

@surli
Copy link
Collaborator

surli commented Jan 8, 2018

Thanks @pvojtechovsky for this refactoring :)

@surli surli merged commit 1d8e608 into INRIA:master Jan 8, 2018
@pvojtechovsky pvojtechovsky deleted the feaRoleSetAddRemove branch September 1, 2018 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants