-
Notifications
You must be signed in to change notification settings - Fork 194
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
Overload method AbstractTreeViewer::internalConditionalExpandToLevel #2692
base: master
Are you sure you want to change the base?
Overload method AbstractTreeViewer::internalConditionalExpandToLevel #2692
Conversation
4381cb8
to
532e4d8
Compare
532e4d8
to
f621202
Compare
I think "internalConditionalExpandToLevel" is the wrong level of abstraction to make an API. Let alone the name "internal" ;-) |
f621202
to
fc46dd4
Compare
Added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to hold back this change until #1072 (review) is resolved?
The method to be modified has been introduced last year, but we may need to change it as there was something like a breaking API change caused by it which we may need to revise.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
fc46dd4
to
904f65b
Compare
Hm, I'd like to have this one and eclipse-jdt/eclipse.jdt.ui#1932 for M2. Why not solve the other issue separately? The fix for #1072 (review) will have to expand widgets and its children regardless of how to do it i.e. it can make (and should) make use of |
I want to have a solution for the other issue soon (before M2), so it should not prevent this from being in before M2. It may just make the resolution more complicated as it further a method whose extract may have been invalid and needs to be reverted.
If you have a solution, it would be great if you can share. I did not think about the solution so far as I just got aware of the issue. To restore the original recursive behavior we may need to revert the method extraction, which will also affect this change. |
I still don't see why the need of postponing this change. If you need to revert the other change then you still can integrate this PR into the other one. Why pass the buck and make this PR adapt to other one? Also keep in mind that I don't only want to merge this PR, I also want the one in JDT so @jukzi would have to rush that one too which can lead to more errors. |
As I said:
We potentially have to replace the extracted method with an inlined (recursively called one) again, so you cannot simply add new parameters like you are doing in tihs PR.
Because it might be possible that the other PR was invalid and this one would be as well (for the same reason, an API breakage). I don't understand the problem with just waiting for some investigation. I will try to do that asap (hopefully today, maybe tomorrow). |
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
maybe you could agree on a setExpandDuplicate(boolean) which should be independent on how its implemented? |
I currently have no strong opinion for or against any possible solution. This solution is also fine for me if will still be possible to apply it once the regression is fixed. I have just created a PR with a potential fix of the regression: |
@HeikoKlare I just reviewed your PR and I think I can adapt this one to it. Let's process yours with a higher priority and then, once it's merged, I can adapt this one. |
The reasons I'm trying to avoid the usage of "duplicate" are :
A solution that gives the chance to interrupt the unfolding and leaves the details to the consumer looks more flexible to me, that's why I tried to implement something more general by providing the |
Because of this JFace has ViewerComparator to compare two items. Also trees are allowed to contain "duplicates" of course. One major drawback and performance problem of trees is that it does not maintain a parent<->child relation (TreeNodeContentProvider try to solve this but requires special consideration of the elements shown in a tree). |
c2eddc0
to
b579e04
Compare
I've adapted this PR according to the changes in #2707. This PR is ready to be reviewed again. |
@@ -139,6 +140,8 @@ public abstract class AbstractTreeViewer extends ColumnViewer { | |||
*/ | |||
private boolean isTreePathContentProvider = false; | |||
|
|||
private Predicate<Item> shouldItemExpand; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is to be a field that has a meaning across method calls, it should, e.g., be filled during intialization. If this value is only relevant during a call of expandToLevel
(or other) method (and thus reinitialized in every call of that method), it should not be a field, as it is specific to the execution time of that method.
You see the issues with this in the currently failing tests: there are other callers of internalCustomizedExpandToLevel
, which accesses this field without it being initialized.
So I see two options:
- This predicate needs to be created within the method it is valid in and passed through the methods called from there, if necessary
- This precidate may be initialized at object initialization with a proper invariant holding for it during the object lifecycle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initialized it in the constructor too to avoid NPEs.
The tricky part is passing it all the way down through the method calls until it reaches internalCustomizedExpandToLevel
without adding an extra parameter (or overloading) internalExpandToLevel(Widget widget, int level)
. Which is why I was only able to support the use cases where the call comes through expandToLevel(...)
.
Do you see any better way to do it? I couldn't come up with any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still means you are abusing a field of class to actually pass a method parameter. Fields of classes need to have a proper (or at least a reasonable) invariant they fulfill, but this one actually has not reasonable invariant (apart from "state x regarding last execution of y") as it is actually a method parameter.
I understand that changing the method signature is not easy/possible, but in my opinion solving this by abusing a field as a method parameter is an error prone design flaw. If you need to reinitialize the shouldItemExpand
in some of the methods calling internalCustomizedExpandToLevel
, why not in the others? Is there potentially some state in the predicate delivered by createShouldItemExpand
? Then that one will usually be invalid while executing internalCustomizedExpandToLevel
without having it properly initialized.
Wouldn't it be possible to achieve the same without any extension to AbstractTreeViewer by simply implementing the according subtype with an overwrittten expandToLevel
, adding the predicate creation at the beginning of the method, and then consuming it in an overwritten setExpanded
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consuming it in setExpanded
won't work because the execution needs to be stopped in its consumer (internalCustomizedExpandToLevel
) which can only be achieved by changing its return value to boolean
(API change, since it's a protected method) and doing an early return.
I've been looking at other subclasses of AbstractTreeViewer
and I noticed that they end up hacking its way into the expansion mechanism by overriding methods. I think this may be a consequence of the little flexibility that the class offers. How about adding hook 2 methods that will be called only once right before and after the expansion runs? This would give the consumer/subclasses the chance to cleanly preserve some state outside AbstractTreeViewer
and hopefully avoid future hacks.
b579e04
to
5600a40
Compare
See @jukzi's comment: #2684 (comment)
Is required by