Running the computation of remote usages on background, workarounding too broad events from the NbProject causing troubles in finding correct nodes inside the PackageView
authorJan Lahoda <jlahoda@netbeans.org>
Wed, 29 Jun 2011 14:57:07 +0200
changeset 6150558321930c2
parent 614 22655f5f498e
child 616 c37de869da36
Running the computation of remote usages on background, workarounding too broad events from the NbProject causing troubles in finding correct nodes inside the PackageView
remoting/ide/usages/nbproject/genfiles.properties
remoting/ide/usages/nbproject/project.xml
remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/Nodes.java
remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/RemoteUsages.java
     1.1 --- a/remoting/ide/usages/nbproject/genfiles.properties	Tue Jun 28 16:04:04 2011 +0200
     1.2 +++ b/remoting/ide/usages/nbproject/genfiles.properties	Wed Jun 29 14:57:07 2011 +0200
     1.3 @@ -1,8 +1,8 @@
     1.4 -build.xml.data.CRC32=1b87e477
     1.5 +build.xml.data.CRC32=6f03c856
     1.6  build.xml.script.CRC32=58a6b47a
     1.7  build.xml.stylesheet.CRC32=a56c6a5b@1.47
     1.8  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     1.9  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    1.10 -nbproject/build-impl.xml.data.CRC32=1b87e477
    1.11 +nbproject/build-impl.xml.data.CRC32=6f03c856
    1.12  nbproject/build-impl.xml.script.CRC32=583fd407
    1.13  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.47
     2.1 --- a/remoting/ide/usages/nbproject/project.xml	Tue Jun 28 16:04:04 2011 +0200
     2.2 +++ b/remoting/ide/usages/nbproject/project.xml	Wed Jun 29 14:57:07 2011 +0200
     2.3 @@ -58,6 +58,15 @@
     2.4                      </run-dependency>
     2.5                  </dependency>
     2.6                  <dependency>
     2.7 +                    <code-name-base>org.netbeans.modules.project.ant</code-name-base>
     2.8 +                    <build-prerequisite/>
     2.9 +                    <compile-dependency/>
    2.10 +                    <run-dependency>
    2.11 +                        <release-version>1</release-version>
    2.12 +                        <specification-version>1.43</specification-version>
    2.13 +                    </run-dependency>
    2.14 +                </dependency>
    2.15 +                <dependency>
    2.16                      <code-name-base>org.netbeans.modules.projectapi</code-name-base>
    2.17                      <build-prerequisite/>
    2.18                      <compile-dependency/>
    2.19 @@ -101,6 +110,14 @@
    2.20                      </run-dependency>
    2.21                  </dependency>
    2.22                  <dependency>
    2.23 +                    <code-name-base>org.openide.dialogs</code-name-base>
    2.24 +                    <build-prerequisite/>
    2.25 +                    <compile-dependency/>
    2.26 +                    <run-dependency>
    2.27 +                        <specification-version>7.21</specification-version>
    2.28 +                    </run-dependency>
    2.29 +                </dependency>
    2.30 +                <dependency>
    2.31                      <code-name-base>org.openide.explorer</code-name-base>
    2.32                      <build-prerequisite/>
    2.33                      <compile-dependency/>
     3.1 --- a/remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/Nodes.java	Tue Jun 28 16:04:04 2011 +0200
     3.2 +++ b/remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/Nodes.java	Wed Jun 29 14:57:07 2011 +0200
     3.3 @@ -48,13 +48,16 @@
     3.4  import com.sun.source.util.SourcePositions;
     3.5  import com.sun.source.util.TreePathScanner;
     3.6  import java.awt.Image;
     3.7 +import java.beans.PropertyChangeEvent;
     3.8  import java.io.IOException;
     3.9 +import java.lang.reflect.Field;
    3.10  import java.util.ArrayList;
    3.11  import java.util.Collection;
    3.12  import java.util.HashMap;
    3.13  import java.util.LinkedList;
    3.14  import java.util.List;
    3.15  import java.util.Map;
    3.16 +import java.util.concurrent.Callable;
    3.17  import java.util.concurrent.atomic.AtomicBoolean;
    3.18  import java.util.logging.Level;
    3.19  import java.util.logging.Logger;
    3.20 @@ -65,6 +68,7 @@
    3.21  import javax.lang.model.element.TypeElement;
    3.22  import javax.lang.model.type.TypeKind;
    3.23  import javax.swing.Action;
    3.24 +import javax.swing.SwingUtilities;
    3.25  import org.netbeans.api.java.classpath.ClassPath;
    3.26  import org.netbeans.api.java.classpath.GlobalPathRegistry;
    3.27  import org.netbeans.api.java.source.CompilationController;
    3.28 @@ -79,6 +83,7 @@
    3.29  import org.netbeans.api.project.FileOwnerQuery;
    3.30  import org.netbeans.api.project.Project;
    3.31  import org.netbeans.api.project.ProjectUtils;
    3.32 +import org.netbeans.spi.project.support.ant.PropertyEvaluator;
    3.33  import org.netbeans.spi.project.ui.LogicalViewProvider;
    3.34  import org.openide.actions.OpenAction;
    3.35  import org.openide.cookies.EditorCookie;
    3.36 @@ -93,7 +98,11 @@
    3.37  import org.openide.nodes.Children;
    3.38  import org.openide.nodes.FilterNode;
    3.39  import org.openide.nodes.Node;
    3.40 +import org.openide.nodes.NodeEvent;
    3.41 +import org.openide.nodes.NodeListener;
    3.42 +import org.openide.nodes.NodeMemberEvent;
    3.43  import org.openide.nodes.NodeOp;
    3.44 +import org.openide.nodes.NodeReorderEvent;
    3.45  import org.openide.text.Line;
    3.46  import org.openide.util.Exceptions;
    3.47  import org.openide.util.ImageUtilities;
    3.48 @@ -124,6 +133,9 @@
    3.49              }
    3.50  
    3.51              projectFiles.add(file);
    3.52 +
    3.53 +            //XXX: workarounding NbProject's Evaluator, which is too stupid to fire meaningfull property events, which leads to PackageView rebuilding inadvertedly itself due to virtual CONTAINERSHIP change:
    3.54 +            ClassPath.getClassPath(file, ClassPath.COMPILE).getRoots();
    3.55          }
    3.56  
    3.57          projects.remove(null);//XXX!!!XXX
    3.58 @@ -137,8 +149,8 @@
    3.59          return new AbstractNode(new DirectChildren(nodes));
    3.60      }
    3.61  
    3.62 -    private static Node constructSemiLogicalView(final Project p, Iterable<? extends FileObject> files, ElementHandle<?> eh) {
    3.63 -        LogicalViewProvider lvp = p.getLookup().lookup(LogicalViewProvider.class);
    3.64 +    private static Node constructSemiLogicalView(final Project p, final Iterable<? extends FileObject> files, ElementHandle<?> eh) {
    3.65 +        final LogicalViewProvider lvp = p.getLookup().lookup(LogicalViewProvider.class);
    3.66          final Node view;
    3.67  
    3.68          if (lvp != null) {
    3.69 @@ -152,38 +164,7 @@
    3.70              }
    3.71          }
    3.72  
    3.73 -        Collection<Node> fileNodes = new ArrayList<Node>();
    3.74 -
    3.75 -        for (FileObject file : files) {
    3.76 -            Node foundChild = locateChild(view, lvp, file);
    3.77 -
    3.78 -            if (foundChild == null) {
    3.79 -                Node n = new AbstractNode(Children.LEAF) {
    3.80 -                    @Override
    3.81 -                    public Image getIcon(int type) {
    3.82 -                        return ImageUtilities.icon2Image(ProjectUtils.getInformation(p).getIcon());
    3.83 -                    }
    3.84 -                    @Override
    3.85 -                    public Image getOpenedIcon(int type) {
    3.86 -                        return getIcon(type);
    3.87 -                    }
    3.88 -                    @Override
    3.89 -                    public String getHtmlDisplayName() {
    3.90 -                        return view.getHtmlDisplayName() != null ? NbBundle.getMessage(Nodes.class, "ERR_ProjectNotSupported", view.getHtmlDisplayName()) : null;
    3.91 -                    }
    3.92 -                    @Override
    3.93 -                    public String getDisplayName() {
    3.94 -                        return NbBundle.getMessage(Nodes.class, "ERR_ProjectNotSupported", view.getDisplayName());
    3.95 -                    }
    3.96 -                };
    3.97 -
    3.98 -                return n;
    3.99 -            }
   3.100 -
   3.101 -            fileNodes.add(foundChild);
   3.102 -        }
   3.103 -
   3.104 -        return new Wrapper(view, fileNodes, eh);
   3.105 +        return new Wrapper(view, new ComputeNodes(files, view, lvp, p), eh);
   3.106      }
   3.107  
   3.108      private static Node locateChild(Node parent, LogicalViewProvider lvp, FileObject file) {
   3.109 @@ -196,7 +177,7 @@
   3.110  
   3.111      private static class Wrapper extends FilterNode {
   3.112  
   3.113 -        public Wrapper(Node orig, Collection<? extends Node> fileNodes, ElementHandle<?> eh) {
   3.114 +        public Wrapper(Node orig, ComputeNodes fileNodes, ElementHandle<?> eh) {
   3.115              super(orig, new WrapperChildren(orig, fileNodes, eh));
   3.116          }
   3.117  
   3.118 @@ -224,10 +205,10 @@
   3.119      private static class WrapperChildren extends Children.Keys<Node> {
   3.120  
   3.121          private final Node orig;
   3.122 -        private final Collection<? extends Node> fileNodes;
   3.123 +        private final ComputeNodes fileNodes;
   3.124          private final ElementHandle<?> eh;
   3.125  
   3.126 -        public WrapperChildren(Node orig, Collection<? extends Node> fileNodes, ElementHandle<?> eh) {
   3.127 +        public WrapperChildren(Node orig, ComputeNodes fileNodes, ElementHandle<?> eh) {
   3.128              this.orig = orig;
   3.129              this.fileNodes = fileNodes;
   3.130              this.eh = eh;
   3.131 @@ -245,7 +226,7 @@
   3.132              List<Node> toSet = new LinkedList<Node>();
   3.133  
   3.134              OUTER: for (Node n : nodes) {
   3.135 -                for (Node c : fileNodes) {
   3.136 +                for (Node c : fileNodes.compute()) {
   3.137                      if (n == c || isParent(n, c)) {
   3.138                          toSet.add(n);
   3.139                          continue OUTER;
   3.140 @@ -258,7 +239,7 @@
   3.141  
   3.142          @Override
   3.143          protected Node[] createNodes(Node key) {
   3.144 -            if (fileNodes.contains(key)) {
   3.145 +            if (fileNodes.compute().contains(key)) {
   3.146                  FileObject file = key.getLookup().lookup(FileObject.class);
   3.147                  Children c = file != null ? Children.create(new UsagesChildren(file, eh), true) : Children.LEAF;
   3.148                  
   3.149 @@ -475,4 +456,56 @@
   3.150  
   3.151          return input;
   3.152      }
   3.153 +
   3.154 +    private static class ComputeNodes  {
   3.155 +
   3.156 +        private final Iterable<? extends FileObject> files;
   3.157 +        private final Node view;
   3.158 +        private final LogicalViewProvider lvp;
   3.159 +        private final Project p;
   3.160 +
   3.161 +        public ComputeNodes(Iterable<? extends FileObject> files, Node view, LogicalViewProvider lvp, Project p) {
   3.162 +            this.files = files;
   3.163 +            this.view = view;
   3.164 +            this.lvp = lvp;
   3.165 +            this.p = p;
   3.166 +        }
   3.167 +        
   3.168 +        private Collection<Node> result;
   3.169 +
   3.170 +        public synchronized Collection<Node> compute() {
   3.171 +            if (result != null) return result;
   3.172 +
   3.173 +            Collection<Node> fileNodes = new ArrayList<Node>();
   3.174 +
   3.175 +            for (FileObject file : files) {
   3.176 +                Node foundChild = locateChild(view, lvp, file);
   3.177 +
   3.178 +                if (foundChild == null) {
   3.179 +                    foundChild = new AbstractNode(Children.LEAF) {
   3.180 +                        @Override
   3.181 +                        public Image getIcon(int type) {
   3.182 +                            return ImageUtilities.icon2Image(ProjectUtils.getInformation(p).getIcon());
   3.183 +                        }
   3.184 +                        @Override
   3.185 +                        public Image getOpenedIcon(int type) {
   3.186 +                            return getIcon(type);
   3.187 +                        }
   3.188 +                        @Override
   3.189 +                        public String getHtmlDisplayName() {
   3.190 +                            return view.getHtmlDisplayName() != null ? NbBundle.getMessage(Nodes.class, "ERR_ProjectNotSupported", view.getHtmlDisplayName()) : null;
   3.191 +                        }
   3.192 +                        @Override
   3.193 +                        public String getDisplayName() {
   3.194 +                            return NbBundle.getMessage(Nodes.class, "ERR_ProjectNotSupported", view.getDisplayName());
   3.195 +                        }
   3.196 +                    };
   3.197 +                }
   3.198 +
   3.199 +                fileNodes.add(foundChild);
   3.200 +            }
   3.201 +
   3.202 +            return result = fileNodes;
   3.203 +        }
   3.204 +    }
   3.205  }
     4.1 --- a/remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/RemoteUsages.java	Tue Jun 28 16:04:04 2011 +0200
     4.2 +++ b/remoting/ide/usages/src/org/netbeans/modules/jackpot30/ide/usages/RemoteUsages.java	Wed Jun 29 14:57:07 2011 +0200
     4.3 @@ -42,6 +42,7 @@
     4.4  package org.netbeans.modules.jackpot30.ide.usages;
     4.5  
     4.6  import com.sun.source.util.TreePath;
     4.7 +import java.awt.Dialog;
     4.8  import java.awt.event.ActionEvent;
     4.9  import java.awt.event.ActionListener;
    4.10  import java.io.File;
    4.11 @@ -52,6 +53,7 @@
    4.12  import java.util.ArrayList;
    4.13  import java.util.List;
    4.14  import javax.lang.model.element.Element;
    4.15 +import javax.swing.SwingUtilities;
    4.16  import javax.swing.text.JTextComponent;
    4.17  import org.netbeans.api.editor.EditorRegistry;
    4.18  import org.netbeans.api.java.source.CompilationController;
    4.19 @@ -61,14 +63,20 @@
    4.20  import org.netbeans.modules.editor.NbEditorUtilities;
    4.21  import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
    4.22  import org.netbeans.modules.jackpot30.remoting.api.WebUtilities;
    4.23 +import org.openide.DialogDescriptor;
    4.24 +import org.openide.DialogDisplayer;
    4.25 +import org.openide.NotifyDescriptor;
    4.26 +import org.openide.NotifyDescriptor.Message;
    4.27  import org.openide.awt.ActionRegistration;
    4.28  import org.openide.awt.ActionReference;
    4.29  import org.openide.awt.ActionReferences;
    4.30  import org.openide.awt.ActionID;
    4.31  import org.openide.filesystems.FileObject;
    4.32  import org.openide.filesystems.FileUtil;
    4.33 +import org.openide.nodes.Node;
    4.34  import org.openide.util.Exceptions;
    4.35  import org.openide.util.NbBundle.Messages;
    4.36 +import org.openide.util.RequestProcessor;
    4.37  
    4.38  @ActionID(category = "Refactoring",
    4.39  id = "org.netbeans.modules.jackpot30.ide.usages.RemoteUsages")
    4.40 @@ -79,51 +87,74 @@
    4.41  @Messages("CTL_RemoteUsages=Find Remote Usages...")
    4.42  public final class RemoteUsages implements ActionListener {
    4.43  
    4.44 +    private final RequestProcessor WORKER = new RequestProcessor(RemoteUsages.class.getName(), 1, false, false);
    4.45 +    
    4.46      public void actionPerformed(ActionEvent e) {
    4.47          JTextComponent comp = EditorRegistry.lastFocusedComponent(); //XXX
    4.48  
    4.49          if (comp == null) return;
    4.50  
    4.51 -        FileObject file = NbEditorUtilities.getFileObject(comp.getDocument());
    4.52 +        final FileObject file = NbEditorUtilities.getFileObject(comp.getDocument());
    4.53          final int pos = comp.getCaretPosition();
    4.54  
    4.55 -        try {
    4.56 -            final ElementHandle<?>[] handle = new ElementHandle<?>[1];
    4.57 -            final String[] serialized = new String[1];
    4.58 -            
    4.59 -            JavaSource.forFileObject(file).runUserActionTask(new Task<CompilationController>() {
    4.60 -                @Override public void run(CompilationController parameter) throws Exception {
    4.61 -                    parameter.toPhase(JavaSource.Phase.RESOLVED);
    4.62 +        DialogDescriptor dd = new DialogDescriptor("Querying remote server(s), please wait", "Please Wait", true, new Object[0], null, DialogDescriptor.DEFAULT_ALIGN, null, null);
    4.63 +        final Dialog d = DialogDisplayer.getDefault().createDialog(dd);
    4.64  
    4.65 -                    TreePath tp = parameter.getTreeUtilities().pathFor(pos);
    4.66 -                    Element el = parameter.getTrees().getElement(tp);
    4.67 +        WORKER.post(new Runnable() {
    4.68 +            @Override public void run() {
    4.69 +                try {
    4.70 +                    final ElementHandle<?>[] handle = new ElementHandle<?>[1];
    4.71 +                    final String[] serialized = new String[1];
    4.72  
    4.73 -                    if (el != null && Common.SUPPORTED_KINDS.contains(el.getKind())) {
    4.74 -                        serialized[0] = serialize(handle[0] = ElementHandle.create(el));
    4.75 +                    JavaSource.forFileObject(file).runUserActionTask(new Task<CompilationController>() {
    4.76 +                        @Override public void run(CompilationController parameter) throws Exception {
    4.77 +                            parameter.toPhase(JavaSource.Phase.RESOLVED);
    4.78 +
    4.79 +                            TreePath tp = parameter.getTreeUtilities().pathFor(pos);
    4.80 +                            Element el = parameter.getTrees().getElement(tp);
    4.81 +
    4.82 +                            if (el != null && Common.SUPPORTED_KINDS.contains(el.getKind())) {
    4.83 +                                serialized[0] = serialize(handle[0] = ElementHandle.create(el));
    4.84 +                            }
    4.85 +                        }
    4.86 +                    }, true);
    4.87 +
    4.88 +                    if (serialized[0] == null) return ; //XXX: warn user!
    4.89 +
    4.90 +                    List<FileObject> result = new ArrayList<FileObject>();
    4.91 +
    4.92 +                    for (RemoteIndex idx : RemoteIndex.loadIndices()) {
    4.93 +                        URI resolved = new URI(idx.remote.toExternalForm() + "/usages/search?path=" + WebUtilities.escapeForQuery(idx.remoteSegment) + "&signatures=" + WebUtilities.escapeForQuery(serialized[0]));
    4.94 +
    4.95 +                        for (String path : WebUtilities.requestStringArrayResponse(resolved)) {
    4.96 +                            File f = new File(idx.folder, path);
    4.97 +
    4.98 +                            result.add(FileUtil.toFileObject(f));
    4.99 +                        }
   4.100                      }
   4.101 -                }
   4.102 -            }, true);
   4.103  
   4.104 -            if (serialized[0] == null) return ; //XXX: warn user!
   4.105 +                    final Node view = Nodes.constructSemiLogicalView(result, handle[0]);
   4.106  
   4.107 -            List<FileObject> result = new ArrayList<FileObject>();
   4.108 -
   4.109 -            for (RemoteIndex idx : RemoteIndex.loadIndices()) {
   4.110 -                URI resolved = new URI(idx.remote.toExternalForm() + "/usages/search?path=" + WebUtilities.escapeForQuery(idx.remoteSegment) + "&signatures=" + WebUtilities.escapeForQuery(serialized[0]));
   4.111 -
   4.112 -                for (String path : WebUtilities.requestStringArrayResponse(resolved)) {
   4.113 -                    File f = new File(idx.folder, path);
   4.114 -
   4.115 -                    result.add(FileUtil.toFileObject(f));
   4.116 +                    SwingUtilities.invokeLater(new Runnable() {
   4.117 +                        @Override public void run() {
   4.118 +                            RemoteUsagesWindowTopComponent.openFor(view);
   4.119 +                        }
   4.120 +                    });
   4.121 +                } catch (URISyntaxException ex) {
   4.122 +                    Exceptions.printStackTrace(ex);
   4.123 +                } catch (IOException ex) {
   4.124 +                    Exceptions.printStackTrace(ex);
   4.125 +                } finally {
   4.126 +                    SwingUtilities.invokeLater(new Runnable() {
   4.127 +                        @Override public void run() {
   4.128 +                            d.setVisible(false);
   4.129 +                        }
   4.130 +                    });
   4.131                  }
   4.132              }
   4.133 +        });
   4.134  
   4.135 -            RemoteUsagesWindowTopComponent.openFor(Nodes.constructSemiLogicalView(result, handle[0]));
   4.136 -        } catch (URISyntaxException ex) {
   4.137 -            Exceptions.printStackTrace(ex);
   4.138 -        } catch (IOException ex) {
   4.139 -            Exceptions.printStackTrace(ex);
   4.140 -        }
   4.141 +        d.setVisible(true);
   4.142      }
   4.143  
   4.144      //XXX: