This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 241009
Collapse All | Expand All

(-)a/csl.api/nbproject/project.properties (-2 / +2 lines)
Lines 40-48 Link Here
40
# Version 2 license, then the option applies only if the new code is
40
# Version 2 license, then the option applies only if the new code is
41
# made subject to such option by the copyright holder.
41
# made subject to such option by the copyright holder.
42
42
43
spec.version.base=2.49.0
43
spec.version.base=2.50.0
44
is.autoload=true
44
is.autoload=true
45
javac.source=1.6
45
javac.source=1.7
46
46
47
javadoc.overview=${basedir}/doc/overview.html
47
javadoc.overview=${basedir}/doc/overview.html
48
javadoc.arch=${basedir}/arch.xml
48
javadoc.arch=${basedir}/arch.xml
(-)a/csl.api/src/org/netbeans/modules/csl/core/SpiSupportAccessor.java (+74 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2015 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.csl.core;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.modules.parsing.spi.support.CancelSupport;
46
import org.openide.util.Parameters;
47
48
/**
49
 *
50
 * @author Tomas Zezula
51
 */
52
public abstract class SpiSupportAccessor {
53
    private static volatile SpiSupportAccessor instance;
54
55
    @NonNull
56
    public static synchronized SpiSupportAccessor getInstance() {
57
        if (instance == null) {
58
            try {
59
                Class.forName(org.netbeans.modules.csl.spi.support.CancelSupport.class.getName(), true, SpiSupportAccessor.class.getClassLoader());
60
                assert instance != null;
61
            } catch (ClassNotFoundException e) {
62
                throw new RuntimeException(e);
63
            }
64
        }
65
        return instance;
66
    }
67
68
    public static void setInstance(@NonNull final SpiSupportAccessor inst) {
69
        Parameters.notNull("inst", inst);   //NOI18N
70
        instance = inst;
71
    }
72
    public abstract void setCancelSupport(@NonNull CancelSupport cancelSupport);
73
    public abstract void removeCancelSupport(@NonNull CancelSupport cancelSupport);
74
}
(-)a/csl.api/src/org/netbeans/modules/csl/editor/overridden/ComputeAnnotations.java (-82 / +84 lines)
Lines 50-56 Link Here
50
import java.util.Map;
50
import java.util.Map;
51
import java.util.Map.Entry;
51
import java.util.Map.Entry;
52
import java.util.Set;
52
import java.util.Set;
53
import java.util.concurrent.atomic.AtomicBoolean;
54
import java.util.logging.Level;
53
import java.util.logging.Level;
55
import java.util.logging.Logger;
54
import java.util.logging.Logger;
56
import javax.swing.text.BadLocationException;
55
import javax.swing.text.BadLocationException;
Lines 68-73 Link Here
68
import org.netbeans.modules.csl.core.GsfHtmlFormatter;
67
import org.netbeans.modules.csl.core.GsfHtmlFormatter;
69
import org.netbeans.modules.csl.core.Language;
68
import org.netbeans.modules.csl.core.Language;
70
import org.netbeans.modules.csl.core.LanguageRegistry;
69
import org.netbeans.modules.csl.core.LanguageRegistry;
70
import org.netbeans.modules.csl.core.SpiSupportAccessor;
71
import org.netbeans.modules.csl.navigation.ElementScanningTask;
71
import org.netbeans.modules.csl.navigation.ElementScanningTask;
72
import org.netbeans.modules.csl.spi.ParserResult;
72
import org.netbeans.modules.csl.spi.ParserResult;
73
import org.netbeans.modules.parsing.api.Embedding;
73
import org.netbeans.modules.parsing.api.Embedding;
Lines 82-88 Link Here
82
import org.netbeans.modules.parsing.spi.Scheduler;
82
import org.netbeans.modules.parsing.spi.Scheduler;
83
import org.netbeans.modules.parsing.spi.SchedulerEvent;
83
import org.netbeans.modules.parsing.spi.SchedulerEvent;
84
import org.netbeans.modules.parsing.spi.SchedulerTask;
84
import org.netbeans.modules.parsing.spi.SchedulerTask;
85
import org.netbeans.modules.parsing.spi.TaskFactory;
85
import org.netbeans.modules.parsing.spi.support.CancelSupport;
86
import org.openide.filesystems.FileObject;
86
import org.openide.filesystems.FileObject;
87
import org.openide.text.NbDocument;
87
import org.openide.text.NbDocument;
88
import org.openide.util.NbBundle;
88
import org.openide.util.NbBundle;
Lines 91-200 Link Here
91
 *
91
 *
92
 * @author lahvac
92
 * @author lahvac
93
 */
93
 */
94
public class ComputeAnnotations extends ParserResultTask<Result> {
94
public final class ComputeAnnotations extends ParserResultTask<Result> {
95
95
96
    private static final Logger LOG = Logger.getLogger(ComputeAnnotations.class.getName());
96
    private static final Logger LOG = Logger.getLogger(ComputeAnnotations.class.getName());
97
    private final AtomicBoolean cancel = new AtomicBoolean();
97
    private final CancelSupport cancel = CancelSupport.create(this);
98
    
98
    
99
    @Override
99
    @Override
100
    public void run(Result result, SchedulerEvent event) {
100
    public void run(Result result, SchedulerEvent event) {
101
        if (!(result instanceof ParserResult)) {
101
        if (!(result instanceof ParserResult)) {
102
            return;
102
            return;
103
        }
103
        }
104
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
105
        try {
106
            final FileObject file = result.getSnapshot().getSource().getFileObject();
104
107
105
        cancel.set(false);
108
            if (file == null) {
106
        
109
                return;
107
        final FileObject file = result.getSnapshot().getSource().getFileObject();
110
            }
108
111
109
        if (file == null) {
112
            final StyledDocument doc = (StyledDocument) result.getSnapshot().getSource().getDocument(false);
110
            return;
111
        }
112
113
113
        final StyledDocument doc = (StyledDocument) result.getSnapshot().getSource().getDocument(false);
114
            if (doc == null) {
115
                return;
116
            }
114
117
115
        if (doc == null) {
118
            final List<IsOverriddenAnnotation> annotations = new LinkedList<IsOverriddenAnnotation>();
116
            return;
119
            try {
117
        }
120
                ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
121
                    public @Override void run(ResultIterator resultIterator) throws Exception {
122
                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
123
                        if(language != null) { //check for non csl results
124
                            StructureScanner scanner = language.getStructure();
125
                            OverridingMethods om = language.getOverridingMethods();
126
                            if (scanner != null && om != null) {
127
                                Parser.Result r = resultIterator.getParserResult();
128
                                if (r instanceof ParserResult) {
129
                                    Map<ElementHandle, Collection<? extends AlternativeLocation>> overriding = new HashMap<ElementHandle, Collection<? extends AlternativeLocation>>();
130
                                    Map<ElementHandle, Collection<? extends AlternativeLocation>> overridden = new HashMap<ElementHandle, Collection<? extends AlternativeLocation>>();
131
                                    Set<ElementHandle> seen = new HashSet<ElementHandle>();
132
                                    Map<ElementHandle, ElementHandle> node2Parent = new HashMap<ElementHandle, ElementHandle>();
118
133
119
        final List<IsOverriddenAnnotation> annotations = new LinkedList<IsOverriddenAnnotation>();
134
                                    List<? extends StructureItem> children = ElementScanningTask.findCachedStructure(resultIterator.getSnapshot(), r);
120
        try {
135
                                    if (children == null) {
121
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
136
                                        long startTime = System.currentTimeMillis();
122
                public @Override void run(ResultIterator resultIterator) throws Exception {
137
                                        children = scanner.scan((ParserResult) r);
123
                    Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
124
                    if(language != null) { //check for non csl results
125
                        StructureScanner scanner = language.getStructure();
126
                        OverridingMethods om = language.getOverridingMethods();
127
                        if (scanner != null && om != null) {
128
                            Parser.Result r = resultIterator.getParserResult();
129
                            if (r instanceof ParserResult) {
130
                                Map<ElementHandle, Collection<? extends AlternativeLocation>> overriding = new HashMap<ElementHandle, Collection<? extends AlternativeLocation>>();
131
                                Map<ElementHandle, Collection<? extends AlternativeLocation>> overridden = new HashMap<ElementHandle, Collection<? extends AlternativeLocation>>();
132
                                Set<ElementHandle> seen = new HashSet<ElementHandle>();
133
                                Map<ElementHandle, ElementHandle> node2Parent = new HashMap<ElementHandle, ElementHandle>();
134
                                
135
                                List<? extends StructureItem> children = ElementScanningTask.findCachedStructure(resultIterator.getSnapshot(), r);
136
                                if (children == null) {
137
                                    long startTime = System.currentTimeMillis();
138
                                    children = scanner.scan((ParserResult) r);
139
138
140
                                    long endTime = System.currentTimeMillis();
139
                                        long endTime = System.currentTimeMillis();
141
                                    Logger.getLogger("TIMER").log(Level.FINE, "Structure (" + language.getMimeType() + ")",
140
                                        Logger.getLogger("TIMER").log(Level.FINE, "Structure (" + language.getMimeType() + ")",
142
                                            new Object[]{file, endTime - startTime});
141
                                                new Object[]{file, endTime - startTime});
143
                                    ElementScanningTask.markProcessed(r, children);
142
                                        ElementScanningTask.markProcessed(r, children);
144
                                }        
143
                                    }
145
                                List<StructureItem> todo = new LinkedList<StructureItem>(children);
144
                                    List<StructureItem> todo = new LinkedList<StructureItem>(children);
146
                                
147
                                while (!todo.isEmpty()) {
148
                                    StructureItem i = todo.remove(0);
149
145
150
                                    todo.addAll(i.getNestedItems());
146
                                    while (!todo.isEmpty()) {
147
                                        StructureItem i = todo.remove(0);
151
148
152
                                    for (StructureItem nested : i.getNestedItems()) {
149
                                        todo.addAll(i.getNestedItems());
153
                                        if (!node2Parent.containsKey(nested.getElementHandle())) {
150
154
                                            node2Parent.put(nested.getElementHandle(), i.getElementHandle());
151
                                        for (StructureItem nested : i.getNestedItems()) {
152
                                            if (!node2Parent.containsKey(nested.getElementHandle())) {
153
                                                node2Parent.put(nested.getElementHandle(), i.getElementHandle());
154
                                            }
155
                                        }
156
157
                                        if (seen.add(i.getElementHandle())) {
158
                                            if (i.getElementHandle().getKind() != ElementKind.CLASS && i.getElementHandle().getKind() != ElementKind.INTERFACE) {
159
                                                Collection<? extends AlternativeLocation> ov = om.overrides((ParserResult) r, i.getElementHandle());
160
161
                                                if (ov != null && !ov.isEmpty()) {
162
                                                    overriding.put(i.getElementHandle(), ov);
163
                                                }
164
                                            }
165
166
                                            if (om.isOverriddenBySupported((ParserResult) r, i.getElementHandle())) {
167
                                                Collection<? extends AlternativeLocation> on = om.overriddenBy((ParserResult) r, i.getElementHandle());
168
169
                                                if (on != null && !on.isEmpty()) {
170
                                                    overridden.put(i.getElementHandle(), on);
171
                                                }
172
                                            }
155
                                        }
173
                                        }
156
                                    }
174
                                    }
157
175
158
                                    if (seen.add(i.getElementHandle())) {
176
                                    createAnnotations((ParserResult) r, doc, overriding, node2Parent, false, annotations);
159
                                        if (i.getElementHandle().getKind() != ElementKind.CLASS && i.getElementHandle().getKind() != ElementKind.INTERFACE) {
177
                                    createAnnotations((ParserResult) r, doc, overridden, node2Parent, true, annotations);
160
                                            Collection<? extends AlternativeLocation> ov = om.overrides((ParserResult) r, i.getElementHandle());
161
162
                                            if (ov != null && !ov.isEmpty()) {
163
                                                overriding.put(i.getElementHandle(), ov);
164
                                            }
165
                                        }
166
167
                                        if (om.isOverriddenBySupported((ParserResult) r, i.getElementHandle())) {
168
                                            Collection<? extends AlternativeLocation> on = om.overriddenBy((ParserResult) r, i.getElementHandle());
169
170
                                            if (on != null && !on.isEmpty()) {
171
                                                overridden.put(i.getElementHandle(), on);
172
                                            }
173
                                        }
174
                                    }
175
                                }
178
                                }
176
177
                                createAnnotations((ParserResult) r, doc, overriding, node2Parent, false, annotations);
178
                                createAnnotations((ParserResult) r, doc, overridden, node2Parent, true, annotations);
179
                            }
179
                            }
180
                        }
180
                        }
181
182
                        for(Embedding e : resultIterator.getEmbeddings()) {
183
                            run(resultIterator.getResultIterator(e));
184
                        }
181
                    }
185
                    }
186
                });
187
            } catch (ParseException e) {
188
                LOG.log(Level.WARNING, null, e);
189
            }
182
190
183
                    for(Embedding e : resultIterator.getEmbeddings()) {
191
            AnnotationsHolder holder = AnnotationsHolder.get(file);
184
                        run(resultIterator.getResultIterator(e));
192
185
                    }
193
            if (holder != null) {
186
                }
194
                holder.setNewAnnotations(annotations);
187
            });
195
            }
188
        } catch (ParseException e) {
196
//          Logger.getLogger("TIMER").log(Level.FINE, "Is Overridden Annotations", new Object[] {info.getFileObject(), end - start});
189
            LOG.log(Level.WARNING, null, e);
197
        } finally {
198
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
190
        }
199
        }
191
200
192
        AnnotationsHolder holder = AnnotationsHolder.get(file);
193
194
        if (holder != null) {
195
            holder.setNewAnnotations(annotations);
196
        }
197
//        Logger.getLogger("TIMER").log(Level.FINE, "Is Overridden Annotations", new Object[] {info.getFileObject(), end - start});
198
    }
201
    }
199
202
200
    private void createAnnotations(ParserResult r, StyledDocument doc, Map<ElementHandle, Collection<? extends AlternativeLocation>> descriptions, Map<ElementHandle, ElementHandle> node2Parent, boolean overridden, List<IsOverriddenAnnotation> annotations) {
203
    private void createAnnotations(ParserResult r, StyledDocument doc, Map<ElementHandle, Collection<? extends AlternativeLocation>> descriptions, Map<ElementHandle, ElementHandle> node2Parent, boolean overridden, List<IsOverriddenAnnotation> annotations) {
Lines 279-287 Link Here
279
282
280
    @Override
283
    @Override
281
    public void cancel() {
284
    public void cancel() {
282
        cancel.set(true);
283
    }
285
    }
284
    
286
285
    private static Position getPosition(final StyledDocument doc, final int offset) {
287
    private static Position getPosition(final StyledDocument doc, final int offset) {
286
        class Impl implements Runnable {
288
        class Impl implements Runnable {
287
            private Position pos;
289
            private Position pos;
(-)a/csl.api/src/org/netbeans/modules/csl/editor/semantic/MarkOccurrencesHighlighter.java (-62 / +57 lines)
Lines 45-51 Link Here
45
45
46
import java.awt.Color;
46
import java.awt.Color;
47
import java.util.ArrayList;
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.List;
48
import java.util.List;
50
import java.util.Map;
49
import java.util.Map;
51
import java.util.SortedSet;
50
import java.util.SortedSet;
Lines 60-70 Link Here
60
import org.netbeans.modules.csl.spi.ParserResult;
59
import org.netbeans.modules.csl.spi.ParserResult;
61
import org.netbeans.modules.csl.core.Language;
60
import org.netbeans.modules.csl.core.Language;
62
import org.netbeans.modules.csl.api.ColoringAttributes.Coloring;
61
import org.netbeans.modules.csl.api.ColoringAttributes.Coloring;
62
import org.netbeans.modules.csl.core.SpiSupportAccessor;
63
import org.netbeans.modules.parsing.api.Snapshot;
63
import org.netbeans.modules.parsing.api.Snapshot;
64
import org.netbeans.modules.parsing.spi.CursorMovedSchedulerEvent;
64
import org.netbeans.modules.parsing.spi.CursorMovedSchedulerEvent;
65
import org.netbeans.modules.parsing.spi.ParserResultTask;
65
import org.netbeans.modules.parsing.spi.ParserResultTask;
66
import org.netbeans.modules.parsing.spi.Scheduler;
66
import org.netbeans.modules.parsing.spi.Scheduler;
67
import org.netbeans.modules.parsing.spi.SchedulerEvent;
67
import org.netbeans.modules.parsing.spi.SchedulerEvent;
68
import org.netbeans.modules.parsing.spi.support.CancelSupport;
68
import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
69
import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
69
import org.openide.ErrorManager;
70
import org.openide.ErrorManager;
70
import org.openide.util.NbBundle;
71
import org.openide.util.NbBundle;
Lines 78-88 Link Here
78
 *
79
 *
79
 * @author Jan Lahoda
80
 * @author Jan Lahoda
80
 */
81
 */
81
public class MarkOccurrencesHighlighter extends ParserResultTask<ParserResult> {
82
public final class MarkOccurrencesHighlighter extends ParserResultTask<ParserResult> {
82
83
83
    private static final Logger LOG = Logger.getLogger(MarkOccurrencesHighlighter.class.getName());
84
    private static final Logger LOG = Logger.getLogger(MarkOccurrencesHighlighter.class.getName());
84
    
85
    
85
    //private FileObject file;
86
    //private FileObject file;
87
    private final CancelSupport cancel = CancelSupport.create(this);
86
    private final Language language;
88
    private final Language language;
87
    private final Snapshot snapshot;
89
    private final Snapshot snapshot;
88
    private int version;
90
    private int version;
Lines 101-159 Link Here
101
//    }
103
//    }
102
//
104
//
103
    public void run(ParserResult info, SchedulerEvent event) {
105
    public void run(ParserResult info, SchedulerEvent event) {
104
        resume();
106
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
105
        
107
        try {
106
        Document doc = snapshot.getSource().getDocument(false);
108
            Document doc = snapshot.getSource().getDocument(false);
107
        
108
        if (doc == null) {
109
            LOG.log(Level.INFO, "MarkOccurencesHighlighter: Cannot get document!"); //NOI18N
110
            return ;
111
        }
112
        
113
        if (!(event instanceof CursorMovedSchedulerEvent)) {
114
            return;
115
        }
116
109
117
        int caretPosition = ((CursorMovedSchedulerEvent) event).getCaretOffset();
110
            if (doc == null) {
118
        
111
                LOG.log(Level.INFO, "MarkOccurencesHighlighter: Cannot get document!"); //NOI18N
119
        if (isCancelled()) {
112
                return ;
120
            return;
113
            }
121
        }
122
        
123
        int snapshotOffset = info.getSnapshot().getEmbeddedOffset(caretPosition);
124
114
125
        if (snapshotOffset == -1) {
115
            if (!(event instanceof CursorMovedSchedulerEvent)) {
126
            // caret offset not part of this lang embedding, ignore, since
116
                return;
127
            // we cannot assume identifiers in different languages match.
117
            }
128
            return;
129
        }
130
118
131
        List<OffsetRange> bag = processImpl(info, doc, caretPosition);
119
            int caretPosition = ((CursorMovedSchedulerEvent) event).getCaretOffset();
132
        if(bag == null) {
133
            //the occurrences finder haven't found anything, just ignore the result
134
            //and keep the previous occurrences
135
            return ;
136
        }
137
120
138
        if (isCancelled()) {
121
            if (cancel.isCancelled()) {
139
            return;
122
                return;
140
        }
123
            }
141
        
142
        GsfSemanticLayer layer = GsfSemanticLayer.getLayer(MarkOccurrencesHighlighter.class, doc);
143
        SortedSet seqs = new TreeSet<SequenceElement>();
144
124
145
        if (bag.size() > 0) {
125
            int snapshotOffset = info.getSnapshot().getEmbeddedOffset(caretPosition);
146
            for (OffsetRange range : bag) {
126
147
                if (range != OffsetRange.NONE) {
127
            if (snapshotOffset == -1) {
148
                    SequenceElement s = new SequenceElement(language, range, MO);
128
                // caret offset not part of this lang embedding, ignore, since
149
                    seqs.add(s);
129
                // we cannot assume identifiers in different languages match.
130
                return;
131
            }
132
133
            List<OffsetRange> bag = processImpl(info, doc, caretPosition);
134
            if(bag == null) {
135
                //the occurrences finder haven't found anything, just ignore the result
136
                //and keep the previous occurrences
137
                return ;
138
            }
139
140
            if (cancel.isCancelled()) {
141
                return;
142
            }
143
144
            GsfSemanticLayer layer = GsfSemanticLayer.getLayer(MarkOccurrencesHighlighter.class, doc);
145
            SortedSet seqs = new TreeSet<SequenceElement>();
146
147
            if (bag.size() > 0) {
148
                for (OffsetRange range : bag) {
149
                    if (range != OffsetRange.NONE) {
150
                        SequenceElement s = new SequenceElement(language, range, MO);
151
                        seqs.add(s);
152
                    }
150
                }
153
                }
151
            }
154
            }
155
156
            layer.setColorings(seqs, version++);
157
158
            OccurrencesMarkProvider.get(doc).setOccurrences(OccurrencesMarkProvider.createMarks(doc, bag, ES_COLOR, NbBundle.getMessage(MarkOccurrencesHighlighter.class, "LBL_ES_TOOLTIP")));
159
        } finally {
160
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
152
        }
161
        }
153
        
154
        layer.setColorings(seqs, version++);
155
        
156
        OccurrencesMarkProvider.get(doc).setOccurrences(OccurrencesMarkProvider.createMarks(doc, bag, ES_COLOR, NbBundle.getMessage(MarkOccurrencesHighlighter.class, "LBL_ES_TOOLTIP")));
157
    }
162
    }
158
    
163
    
159
    @NonNull
164
    @NonNull
Lines 168-174 Link Here
168
            ErrorManager.getDefault().notify(ex);
173
            ErrorManager.getDefault().notify(ex);
169
        }
174
        }
170
175
171
        if (isCancelled()) {
176
        if (cancel.isCancelled()) {
172
            finder.cancel();
177
            finder.cancel();
173
        }
178
        }
174
179
Lines 186-206 Link Here
186
    public Class<? extends Scheduler> getSchedulerClass () {
191
    public Class<? extends Scheduler> getSchedulerClass () {
187
        return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
192
        return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
188
    }
193
    }
189
    
194
190
    private boolean canceled;
195
    @Override
191
    
196
    public final void cancel() {
192
    public final synchronized void cancel() {
193
        canceled = true;
194
    }
197
    }
195
    
198
196
    protected final synchronized boolean isCancelled() {
197
        return canceled;
198
    }
199
    
200
    protected final synchronized void resume() {
201
        canceled = false;
202
    }
203
    
204
    public static AbstractHighlightsContainer getHighlightsBag(Document doc) {
199
    public static AbstractHighlightsContainer getHighlightsBag(Document doc) {
205
        GsfSemanticLayer highlight = GsfSemanticLayer.getLayer(MarkOccurrencesHighlighter.class, doc);
200
        GsfSemanticLayer highlight = GsfSemanticLayer.getLayer(MarkOccurrencesHighlighter.class, doc);
206
        return highlight;
201
        return highlight;
(-)a/csl.api/src/org/netbeans/modules/csl/editor/semantic/SemanticHighlighter.java (-58 / +54 lines)
Lines 58-63 Link Here
58
import org.netbeans.modules.csl.api.SemanticAnalyzer;
58
import org.netbeans.modules.csl.api.SemanticAnalyzer;
59
import org.netbeans.modules.csl.core.Language;
59
import org.netbeans.modules.csl.core.Language;
60
import org.netbeans.modules.csl.core.LanguageRegistry;
60
import org.netbeans.modules.csl.core.LanguageRegistry;
61
import org.netbeans.modules.csl.core.SpiSupportAccessor;
61
import org.netbeans.modules.csl.spi.ParserResult;
62
import org.netbeans.modules.csl.spi.ParserResult;
62
import org.netbeans.modules.parsing.api.Embedding;
63
import org.netbeans.modules.parsing.api.Embedding;
63
import org.netbeans.modules.parsing.api.ParserManager;
64
import org.netbeans.modules.parsing.api.ParserManager;
Lines 65-70 Link Here
65
import org.netbeans.modules.parsing.api.Source;
66
import org.netbeans.modules.parsing.api.Source;
66
import org.netbeans.modules.parsing.api.UserTask;
67
import org.netbeans.modules.parsing.api.UserTask;
67
import org.netbeans.modules.parsing.spi.*;
68
import org.netbeans.modules.parsing.spi.*;
69
import org.netbeans.modules.parsing.spi.support.CancelSupport;
68
70
69
71
70
/**
72
/**
Lines 76-84 Link Here
76
 *
78
 *
77
 * @author Jan Lahoda
79
 * @author Jan Lahoda
78
 */
80
 */
79
public class SemanticHighlighter extends IndexingAwareParserResultTask<ParserResult> {
81
public final class SemanticHighlighter extends IndexingAwareParserResultTask<ParserResult> {
80
82
81
    private static final Logger LOG = Logger.getLogger(SemanticHighlighter.class.getName());
83
    private static final Logger LOG = Logger.getLogger(SemanticHighlighter.class.getName());
84
85
    private final CancelSupport cancel = CancelSupport.create(this);
82
    
86
    
83
    /** Creates a new instance of SemanticHighlighter */
87
    /** Creates a new instance of SemanticHighlighter */
84
    SemanticHighlighter() {
88
    SemanticHighlighter() {
Lines 99-175 Link Here
99
        return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
103
        return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
100
    }
104
    }
101
105
102
    private boolean cancelled;
103
106
104
    public final synchronized void cancel() {
107
    public final void cancel() {
105
        cancelled = true;
106
    }
107
108
    protected final synchronized boolean isCancelled() {
109
        return cancelled;
110
    }
111
112
    protected final synchronized void resume() {
113
        cancelled = false;
114
    }
108
    }
115
109
116
    public @Override void run(ParserResult info, SchedulerEvent event) {
110
    public @Override void run(ParserResult info, SchedulerEvent event) {
117
        resume();
118
        
119
        Document doc = info.getSnapshot().getSource().getDocument(false);
111
        Document doc = info.getSnapshot().getSource().getDocument(false);
120
        if (doc == null) {
112
        if (doc == null) {
121
            return;
113
            return;
122
        }
114
        }
115
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
116
        try {
117
            long startTime = System.currentTimeMillis();
123
118
124
        long startTime = System.currentTimeMillis();
119
            Source source = info.getSnapshot().getSource();
120
            final SortedSet<SequenceElement> newColoring = new TreeSet<SequenceElement>();
121
            try {
122
                ParserManager.parse(Collections.singleton(source), new UserTask() {
123
                    public @Override void run(ResultIterator resultIterator) throws Exception {
124
                        String mimeType = resultIterator.getSnapshot().getMimeType();
125
                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(mimeType);
126
                        if (language != null) {
127
                            ColoringManager manager = language.getColoringManager();
128
                            SemanticAnalyzer task = language.getSemanticAnalyzer();
129
                            if (manager != null && task != null) {
130
                                Parser.Result r = resultIterator.getParserResult();
131
                                if (r instanceof ParserResult) {
132
                                    process(language, (ParserResult) r, newColoring);
133
                                }
134
                            }
135
                        }
125
136
126
        Source source = info.getSnapshot().getSource();
137
                        for(Embedding e : resultIterator.getEmbeddings()) {
127
        final SortedSet<SequenceElement> newColoring = new TreeSet<SequenceElement>();
138
                            if (cancel.isCancelled()) {
128
        try {
139
                                return;
129
            ParserManager.parse(Collections.singleton(source), new UserTask() {
140
                            } else {
130
                public @Override void run(ResultIterator resultIterator) throws Exception {
141
                                run(resultIterator.getResultIterator(e));
131
                    String mimeType = resultIterator.getSnapshot().getMimeType();
132
                    Language language = LanguageRegistry.getInstance().getLanguageByMimeType(mimeType);
133
                    if (language != null) {
134
                        ColoringManager manager = language.getColoringManager();
135
                        SemanticAnalyzer task = language.getSemanticAnalyzer();
136
                        if (manager != null && task != null) {
137
                            Parser.Result r = resultIterator.getParserResult();
138
                            if (r instanceof ParserResult) {
139
                                process(language, (ParserResult) r, newColoring);
140
                            }
142
                            }
141
                        }
143
                        }
142
                    }
144
                    }
145
                });
146
            } catch (ParseException e) {
147
                LOG.log(Level.WARNING, null, e);
148
                return;
149
            }
143
150
144
                    for(Embedding e : resultIterator.getEmbeddings()) {
151
            long endTime = System.currentTimeMillis();
145
                        if (isCancelled()) {
152
            Logger.getLogger("TIMER").log(Level.FINE, "Semantic (" + source.getMimeType() + ")", //NOI18N
146
                            return;
153
                    new Object[] { source.getFileObject(), endTime - startTime});
147
                        } else {
154
148
                            run(resultIterator.getResultIterator(e));
155
            if (cancel.isCancelled()) {
149
                        }
156
                return;
150
                    }
157
            }
158
159
            final GsfSemanticLayer layer = GsfSemanticLayer.getLayer(SemanticHighlighter.class, doc);
160
            SwingUtilities.invokeLater(new Runnable () {
161
                public void run() {
162
    // XXX: parsingapi
163
                    layer.setColorings(newColoring, -1); //version
151
                }
164
                }
152
            });
165
            });
153
        } catch (ParseException e) {
166
        } finally {
154
            LOG.log(Level.WARNING, null, e);
167
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
155
            return;
156
        }
168
        }
157
158
        long endTime = System.currentTimeMillis();
159
        Logger.getLogger("TIMER").log(Level.FINE, "Semantic (" + source.getMimeType() + ")", //NOI18N
160
                new Object[] { source.getFileObject(), endTime - startTime});
161
162
        if (isCancelled()) {
163
            return;
164
        }
165
166
        final GsfSemanticLayer layer = GsfSemanticLayer.getLayer(SemanticHighlighter.class, doc);
167
        SwingUtilities.invokeLater(new Runnable () {
168
            public void run() {
169
// XXX: parsingapi
170
                layer.setColorings(newColoring, -1); //version
171
            }
172
        });
173
    }
169
    }
174
    
170
    
175
171
Lines 294-300 Link Here
294
//        }
290
//        }
295
291
296
292
297
        if (isCancelled()) {
293
        if (cancel.isCancelled()) {
298
            return;
294
            return;
299
        }
295
        }
300
296
Lines 312-318 Link Here
312
                    "(mimepath = " + result.getSnapshot().getMimePath() + ")", ex);
308
                    "(mimepath = " + result.getSnapshot().getMimePath() + ")", ex);
313
        }
309
        }
314
310
315
        if (isCancelled()) {
311
        if (cancel.isCancelled()) {
316
            task.cancel();
312
            task.cancel();
317
            return;
313
            return;
318
        }
314
        }
Lines 330-336 Link Here
330
326
331
                newColoring.add(new SequenceElement(language, range, c));
327
                newColoring.add(new SequenceElement(language, range, c));
332
328
333
                if (isCancelled()) {
329
                if (cancel.isCancelled()) {
334
                    return;
330
                    return;
335
                }
331
                }
336
            }
332
            }
(-)a/csl.api/src/org/netbeans/modules/csl/hints/GsfHintsProvider.java (-29 / +18 lines)
Lines 69-74 Link Here
69
import org.netbeans.modules.csl.api.Hint;
69
import org.netbeans.modules.csl.api.Hint;
70
import org.netbeans.modules.csl.api.OffsetRange;
70
import org.netbeans.modules.csl.api.OffsetRange;
71
import org.netbeans.modules.csl.api.RuleContext;
71
import org.netbeans.modules.csl.api.RuleContext;
72
import org.netbeans.modules.csl.core.SpiSupportAccessor;
72
import org.netbeans.modules.csl.hints.infrastructure.GsfHintsManager;
73
import org.netbeans.modules.csl.hints.infrastructure.GsfHintsManager;
73
import org.netbeans.modules.csl.spi.ParserResult;
74
import org.netbeans.modules.csl.spi.ParserResult;
74
import org.netbeans.modules.parsing.api.Embedding;
75
import org.netbeans.modules.parsing.api.Embedding;
Lines 79-84 Link Here
79
import org.netbeans.modules.parsing.spi.ParseException;
80
import org.netbeans.modules.parsing.spi.ParseException;
80
import org.netbeans.modules.parsing.spi.ParserResultTask;
81
import org.netbeans.modules.parsing.spi.ParserResultTask;
81
import org.netbeans.modules.parsing.spi.SchedulerEvent;
82
import org.netbeans.modules.parsing.spi.SchedulerEvent;
83
import org.netbeans.modules.parsing.spi.support.CancelSupport;
82
import org.netbeans.spi.editor.hints.ErrorDescription;
84
import org.netbeans.spi.editor.hints.ErrorDescription;
83
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
85
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
84
import org.netbeans.spi.editor.hints.HintsController;
86
import org.netbeans.spi.editor.hints.HintsController;
Lines 101-107 Link Here
101
public final class GsfHintsProvider extends ParserResultTask<ParserResult> {
103
public final class GsfHintsProvider extends ParserResultTask<ParserResult> {
102
    
104
    
103
    public static final Logger LOG = Logger.getLogger(GsfHintsProvider.class.getName()); // NOI18N
105
    public static final Logger LOG = Logger.getLogger(GsfHintsProvider.class.getName()); // NOI18N
104
    
106
107
    private final CancelSupport cancel = CancelSupport.create(this);
105
    private FileObject file;
108
    private FileObject file;
106
    
109
    
107
    /**
110
    /**
Lines 133-139 Link Here
133
        }
136
        }
134
        
137
        
135
        for (Error d : errors) {
138
        for (Error d : errors) {
136
            if (isCanceled()) {
139
            if (cancel.isCancelled()) {
137
                return null;
140
                return null;
138
            }
141
            }
139
            
142
            
Lines 178-184 Link Here
178
            final String desc = d.getDisplayName();
181
            final String desc = d.getDisplayName();
179
            final Position[] range = getLine(d, doc, position, endPosition);
182
            final Position[] range = getLine(d, doc, position, endPosition);
180
            
183
            
181
            if (isCanceled()) {
184
            if (cancel.isCancelled()) {
182
                return null;
185
                return null;
183
            }
186
            }
184
            
187
            
Lines 189-195 Link Here
189
            descs.add(ErrorDescriptionFactory.createErrorDescription(errorKind2Severity.get(d.getSeverity()), desc, ehm, doc, range[0], range[1]));
192
            descs.add(ErrorDescriptionFactory.createErrorDescription(errorKind2Severity.get(d.getSeverity()), desc, ehm, doc, range[0], range[1]));
190
        }
193
        }
191
        
194
        
192
        if (isCanceled()) {
195
        if (cancel.isCancelled()) {
193
            return null;
196
            return null;
194
        }
197
        }
195
        
198
        
Lines 209-215 Link Here
209
        // under the document read-lock.
212
        // under the document read-lock.
210
        doc.render(new Runnable() {
213
        doc.render(new Runnable() {
211
            public void run() {
214
            public void run() {
212
                if (isCanceled()) {
215
                if (cancel.isCancelled()) {
213
                    return;
216
                    return;
214
                }
217
                }
215
                ret[0] = getLine0(d, doc, startOffset, endOffset);
218
                ret[0] = getLine0(d, doc, startOffset, endOffset);
Lines 259-265 Link Here
259
        int len = doc.getLength();
262
        int len = doc.getLength();
260
263
261
        if (startOffsetFinal > len || endOffsetFinal > len) {
264
        if (startOffsetFinal > len || endOffsetFinal > len) {
262
            if (!isCanceled() && LOG.isLoggable(Level.WARNING)) {
265
            if (!cancel.isCancelled() && LOG.isLoggable(Level.WARNING)) {
263
                LOG.log(Level.WARNING, "document changed, but not canceled?" );
266
                LOG.log(Level.WARNING, "document changed, but not canceled?" );
264
                LOG.log(Level.WARNING, "len = " + len );
267
                LOG.log(Level.WARNING, "len = " + len );
265
                LOG.log(Level.WARNING, "startOffset = " + startOffsetFinal );
268
                LOG.log(Level.WARNING, "startOffset = " + startOffsetFinal );
Lines 279-307 Link Here
279
        
282
        
280
        return result;
283
        return result;
281
    }
284
    }
282
    
285
283
    private boolean cancel;
286
284
    
285
    synchronized boolean isCanceled() {
286
        return cancel;
287
    }
288
    
289
    @Override
287
    @Override
290
    public void cancel() {
288
    public void cancel() {
291
        HintsProvider curProvider;
289
        final HintsProvider curProvider = this.pendingProvider;
292
        synchronized (this) {
293
            curProvider = this.pendingProvider;
294
            cancel = true;
295
        }
296
        if (curProvider != null) {
290
        if (curProvider != null) {
297
            curProvider.cancel();
291
            curProvider.cancel();
298
        }
292
        }
299
    }
293
    }
300
    
294
301
    synchronized void resume() {
302
        cancel = false;
303
    }
304
    
305
    private List<Error> processProviderErrors(
295
    private List<Error> processProviderErrors(
306
            final List<ErrorDescription> descriptions, 
296
            final List<ErrorDescription> descriptions, 
307
            Snapshot topLevelSnapshot, final ParserResult r, final Language language) throws ParseException {
297
            Snapshot topLevelSnapshot, final ParserResult r, final Language language) throws ParseException {
Lines 324-330 Link Here
324
        try {
314
        try {
325
            synchronized (this) {
315
            synchronized (this) {
326
                pendingProvider = provider;
316
                pendingProvider = provider;
327
                if (isCanceled()) {
317
                if (cancel.isCancelled()) {
328
                    return errors;
318
                    return errors;
329
                }
319
                }
330
            }
320
            }
Lines 377-383 Link Here
377
        
367
        
378
        for(Embedding e : resultIterator.getEmbeddings()) {
368
        for(Embedding e : resultIterator.getEmbeddings()) {
379
            try {
369
            try {
380
                if (isCanceled()) {
370
                if (cancel.isCancelled()) {
381
                    return;
371
                    return;
382
                }
372
                }
383
            } catch (Exception ex) {
373
            } catch (Exception ex) {
Lines 429-443 Link Here
429
    }
419
    }
430
    
420
    
431
    public @Override void run(ParserResult result, SchedulerEvent event) {
421
    public @Override void run(ParserResult result, SchedulerEvent event) {
432
        resume();
433
        
434
        final Document doc = getDocument();
422
        final Document doc = getDocument();
435
        
436
        if (doc == null) {
423
        if (doc == null) {
437
            LOG.log(Level.INFO, "SemanticHighlighter: Cannot get document!");
424
            LOG.log(Level.INFO, "SemanticHighlighter: Cannot get document!");
438
            return ;
425
            return ;
439
        }
426
        }
440
        
427
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
441
        try {
428
        try {
442
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
429
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
443
                public @Override void run(ResultIterator resultIterator) throws ParseException {
430
                public @Override void run(ResultIterator resultIterator) throws ParseException {
Lines 447-452 Link Here
447
            });
434
            });
448
        } catch (ParseException e) {
435
        } catch (ParseException e) {
449
            LOG.log(Level.WARNING, null, e);
436
            LOG.log(Level.WARNING, null, e);
437
        } finally {
438
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
450
        }
439
        }
451
    }
440
    }
452
    
441
    
(-)a/csl.api/src/org/netbeans/modules/csl/hints/infrastructure/HintsTask.java (-23 / +12 lines)
Lines 53-58 Link Here
53
import org.netbeans.modules.csl.core.LanguageRegistry;
53
import org.netbeans.modules.csl.core.LanguageRegistry;
54
import org.netbeans.modules.csl.api.Hint;
54
import org.netbeans.modules.csl.api.Hint;
55
import org.netbeans.modules.csl.api.RuleContext;
55
import org.netbeans.modules.csl.api.RuleContext;
56
import org.netbeans.modules.csl.core.SpiSupportAccessor;
56
import org.netbeans.modules.csl.spi.ParserResult;
57
import org.netbeans.modules.csl.spi.ParserResult;
57
import org.netbeans.modules.parsing.api.Embedding;
58
import org.netbeans.modules.parsing.api.Embedding;
58
import org.netbeans.modules.parsing.api.ParserManager;
59
import org.netbeans.modules.parsing.api.ParserManager;
Lines 63-68 Link Here
63
import org.netbeans.modules.parsing.spi.ParserResultTask;
64
import org.netbeans.modules.parsing.spi.ParserResultTask;
64
import org.netbeans.modules.parsing.spi.Scheduler;
65
import org.netbeans.modules.parsing.spi.Scheduler;
65
import org.netbeans.modules.parsing.spi.SchedulerEvent;
66
import org.netbeans.modules.parsing.spi.SchedulerEvent;
67
import org.netbeans.modules.parsing.spi.support.CancelSupport;
66
import org.netbeans.spi.editor.hints.ErrorDescription;
68
import org.netbeans.spi.editor.hints.ErrorDescription;
67
import org.netbeans.spi.editor.hints.HintsController;
69
import org.netbeans.spi.editor.hints.HintsController;
68
70
Lines 71-81 Link Here
71
 * 
73
 * 
72
 * @author Tor Norbye
74
 * @author Tor Norbye
73
 */
75
 */
74
public class HintsTask extends ParserResultTask<ParserResult> {
76
public final class HintsTask extends ParserResultTask<ParserResult> {
75
77
76
    private static final Logger LOG = Logger.getLogger(HintsTask.class.getName());
78
    private static final Logger LOG = Logger.getLogger(HintsTask.class.getName());
77
    private volatile boolean cancelled = false;
79
    private final CancelSupport cancel = CancelSupport.create(this);
78
    
80
79
    /**
81
    /**
80
     * Tracks the HintsProvider being executed, so it can be cancelled.
82
     * Tracks the HintsProvider being executed, so it can be cancelled.
81
     */
83
     */
Lines 85-94 Link Here
85
    }
87
    }
86
    
88
    
87
    public @Override void run(ParserResult result, SchedulerEvent event) {
89
    public @Override void run(ParserResult result, SchedulerEvent event) {
88
        resume();
90
        final List<ErrorDescription> descriptions = new ArrayList<>();
89
        
91
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
90
        final List<ErrorDescription> descriptions = new ArrayList<ErrorDescription>();
91
92
        try {
92
        try {
93
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
93
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
94
                public @Override void run(ResultIterator resultIterator) throws ParseException {
94
                public @Override void run(ResultIterator resultIterator) throws ParseException {
Lines 131-137 Link Here
131
                    try {
131
                    try {
132
                        synchronized (HintsTask.this) {
132
                        synchronized (HintsTask.this) {
133
                            pendingProvider = provider;
133
                            pendingProvider = provider;
134
                            if (isCancelled()) {
134
                            if (cancel.isCancelled()) {
135
                                return;
135
                                return;
136
                            }
136
                            }
137
                        }
137
                        }
Lines 140-146 Link Here
140
                        pendingProvider = null;
140
                        pendingProvider = null;
141
                    }
141
                    }
142
142
143
                    if (isCancelled()) {
143
                    if (cancel.isCancelled()) {
144
                        return;
144
                        return;
145
                    }
145
                    }
146
146
Lines 153-160 Link Here
153
            });
153
            });
154
        } catch (ParseException e) {
154
        } catch (ParseException e) {
155
            LOG.log(Level.WARNING, null, e);
155
            LOG.log(Level.WARNING, null, e);
156
        } finally {
157
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
156
        }
158
        }
157
158
        HintsController.setErrors(result.getSnapshot().getSource().getFileObject(), HintsTask.class.getName(), descriptions);
159
        HintsController.setErrors(result.getSnapshot().getSource().getFileObject(), HintsTask.class.getName(), descriptions);
159
    }
160
    }
160
161
Lines 167-187 Link Here
167
    }
168
    }
168
169
169
    public @Override void cancel() {
170
    public @Override void cancel() {
170
        HintsProvider proc;
171
        final HintsProvider proc = pendingProvider;
171
        synchronized  (this) {
172
            proc = pendingProvider;
173
            cancelled = true;
174
        }
175
        if (proc != null) {
172
        if (proc != null) {
176
            proc.cancel();
173
            proc.cancel();
177
        }
174
        }
178
    }
175
    }
179
180
    private synchronized void resume() {
181
        cancelled = false;
182
    }
183
184
    private synchronized boolean isCancelled() {
185
        return cancelled;
186
    }
187
}
176
}
(-)a/csl.api/src/org/netbeans/modules/csl/hints/infrastructure/SelectionHintsTask.java (-76 / +71 lines)
Lines 52-57 Link Here
52
import org.netbeans.modules.csl.api.HintsProvider;
52
import org.netbeans.modules.csl.api.HintsProvider;
53
import org.netbeans.modules.csl.api.RuleContext;
53
import org.netbeans.modules.csl.api.RuleContext;
54
import org.netbeans.modules.csl.core.LanguageRegistry;
54
import org.netbeans.modules.csl.core.LanguageRegistry;
55
import org.netbeans.modules.csl.core.SpiSupportAccessor;
55
import org.netbeans.modules.parsing.api.ResultIterator;
56
import org.netbeans.modules.parsing.api.ResultIterator;
56
import org.netbeans.modules.parsing.spi.Parser;
57
import org.netbeans.modules.parsing.spi.Parser;
57
import org.netbeans.modules.parsing.spi.Scheduler;
58
import org.netbeans.modules.parsing.spi.Scheduler;
Lines 62-67 Link Here
62
import org.netbeans.modules.parsing.spi.ParseException;
63
import org.netbeans.modules.parsing.spi.ParseException;
63
import org.netbeans.modules.parsing.spi.ParserResultTask;
64
import org.netbeans.modules.parsing.spi.ParserResultTask;
64
import org.netbeans.modules.parsing.spi.SchedulerEvent;
65
import org.netbeans.modules.parsing.spi.SchedulerEvent;
66
import org.netbeans.modules.parsing.spi.support.CancelSupport;
65
import org.netbeans.spi.editor.hints.ErrorDescription;
67
import org.netbeans.spi.editor.hints.ErrorDescription;
66
import org.netbeans.spi.editor.hints.HintsController;
68
import org.netbeans.spi.editor.hints.HintsController;
67
import org.openide.filesystems.FileObject;
69
import org.openide.filesystems.FileObject;
Lines 70-79 Link Here
70
 *
72
 *
71
 * @author Tor Norbye
73
 * @author Tor Norbye
72
 */
74
 */
73
public class SelectionHintsTask extends ParserResultTask<ParserResult> {
75
public final class SelectionHintsTask extends ParserResultTask<ParserResult> {
74
    
76
    
75
    private static final Logger LOG = Logger.getLogger(SelectionHintsTask.class.getName());
77
    private static final Logger LOG = Logger.getLogger(SelectionHintsTask.class.getName());
76
    private volatile boolean cancelled = false;
78
    private final CancelSupport cancel = CancelSupport.create(this);
77
    
79
    
78
    /**
80
    /**
79
     * Tracks the HintsProvider being executed, so it can be cancelled.
81
     * Tracks the HintsProvider being executed, so it can be cancelled.
Lines 84-171 Link Here
84
    }
86
    }
85
    
87
    
86
    public @Override void run(ParserResult result, SchedulerEvent event) {
88
    public @Override void run(ParserResult result, SchedulerEvent event) {
87
        resume();
88
89
89
        final FileObject fileObject = result.getSnapshot().getSource().getFileObject();
90
        final FileObject fileObject = result.getSnapshot().getSource().getFileObject();
90
        if (fileObject == null || isCancelled()) {
91
        if (fileObject == null || cancel.isCancelled()) {
91
            return;
92
            return;
92
        }
93
        }
93
94
94
        if (!(event instanceof CursorMovedSchedulerEvent) || isCancelled()) {
95
        if (!(event instanceof CursorMovedSchedulerEvent) || cancel.isCancelled()) {
95
            return;
96
            return;
96
        }
97
        }
97
98
98
        // Do we have a selection? If so, don't do suggestions
99
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
99
        CursorMovedSchedulerEvent evt = (CursorMovedSchedulerEvent) event;
100
        try {
100
        final int[] range = new int [] {
101
            // Do we have a selection? If so, don't do suggestions
101
            Math.min(evt.getMarkOffset(), evt.getCaretOffset()),
102
            CursorMovedSchedulerEvent evt = (CursorMovedSchedulerEvent) event;
102
            Math.max(evt.getMarkOffset(), evt.getCaretOffset())
103
            final int[] range = new int [] {
103
        };
104
                Math.min(evt.getMarkOffset(), evt.getCaretOffset()),
104
        if (range == null || range.length != 2 || range[0] == -1 || range[1] == -1 || range[0] == range[1]) {
105
                Math.max(evt.getMarkOffset(), evt.getCaretOffset())
105
            HintsController.setErrors(fileObject, SelectionHintsTask.class.getName(), Collections.<ErrorDescription>emptyList());
106
            };
106
            return;
107
            if (range == null || range.length != 2 || range[0] == -1 || range[1] == -1 || range[0] == range[1]) {
107
        }
108
                HintsController.setErrors(fileObject, SelectionHintsTask.class.getName(), Collections.<ErrorDescription>emptyList());
109
                return;
110
            }
108
111
109
        try {
112
            try {
110
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
113
                ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
111
                public @Override void run(ResultIterator resultIterator) throws Exception {
114
                    public @Override void run(ResultIterator resultIterator) throws Exception {
112
                    Parser.Result r = resultIterator.getParserResult(range[0]);
115
                        Parser.Result r = resultIterator.getParserResult(range[0]);
113
                    if(!(r instanceof ParserResult)) {
116
                        if(!(r instanceof ParserResult)) {
114
                        return ;
117
                            return ;
115
                    }
118
                        }
116
                    Language language = LanguageRegistry.getInstance().getLanguageByMimeType(r.getSnapshot().getMimeType());
119
                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(r.getSnapshot().getMimeType());
117
                    if (language == null || isCancelled()) {
120
                        if (language == null || cancel.isCancelled()) {
118
                        return;
121
                            return;
119
                    }
122
                        }
120
123
121
                    HintsProvider provider = language.getHintsProvider();
124
                        HintsProvider provider = language.getHintsProvider();
122
                    if (provider == null || isCancelled()) {
125
                        if (provider == null || cancel.isCancelled()) {
123
                        return;
126
                            return;
124
                    }
127
                        }
125
128
126
                    GsfHintsManager manager = language.getHintsManager();
129
                        GsfHintsManager manager = language.getHintsManager();
127
                    if (manager == null || isCancelled()) {
130
                        if (manager == null || cancel.isCancelled()) {
128
                        return;
131
                            return;
129
                    }
132
                        }
130
133
131
                    List<ErrorDescription> description = new ArrayList<ErrorDescription>();
134
                        List<ErrorDescription> description = new ArrayList<ErrorDescription>();
132
                    List<Hint> hints = new ArrayList<Hint>();
135
                        List<Hint> hints = new ArrayList<Hint>();
133
136
134
                    RuleContext ruleContext = manager.createRuleContext((ParserResult) r, language, -1, range[0], range[1]);
137
                        RuleContext ruleContext = manager.createRuleContext((ParserResult) r, language, -1, range[0], range[1]);
135
                    if (ruleContext != null) {
138
                        if (ruleContext != null) {
136
                        try {
139
                            try {
137
                            synchronized (this) {
140
                                synchronized (this) {
138
                                pendingProvider = provider;
141
                                    pendingProvider = provider;
139
                                if (isCancelled()) {
142
                                    if (cancel.isCancelled()) {
143
                                        return;
144
                                    }
145
                                }
146
                                provider.computeSelectionHints(manager, ruleContext, hints, range[0], range[1]);
147
                            } finally {
148
                                pendingProvider = null;
149
                            }
150
151
                            for (int i = 0; i < hints.size(); i++) {
152
                                Hint hint= hints.get(i);
153
154
                                if (cancel.isCancelled()) {
140
                                    return;
155
                                    return;
141
                                }
156
                                }
157
158
                                ErrorDescription desc = manager.createDescription(hint, ruleContext, false, i == hints.size()-1);
159
                                description.add(desc);
142
                            }
160
                            }
143
                            provider.computeSelectionHints(manager, ruleContext, hints, range[0], range[1]);
144
                        } finally {
145
                            pendingProvider = null;
146
                        }
161
                        }
147
162
148
                        for (int i = 0; i < hints.size(); i++) {
163
                        if (cancel.isCancelled()) {
149
                            Hint hint= hints.get(i);
164
                            return;
165
                        }
150
166
151
                            if (isCancelled()) {
167
                        HintsController.setErrors(fileObject, SelectionHintsTask.class.getName(), description);
152
                                return;
153
                            }
154
                            
155
                            ErrorDescription desc = manager.createDescription(hint, ruleContext, false, i == hints.size()-1);
156
                            description.add(desc);
157
                        }
158
                    }
168
                    }
159
169
                });
160
                    if (isCancelled()) {
170
            } catch (ParseException e) {
161
                        return;
171
                LOG.log(Level.WARNING, null, e);
162
                    }
172
            }
163
173
        } finally {
164
                    HintsController.setErrors(fileObject, SelectionHintsTask.class.getName(), description);
174
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
165
                }
166
            });
167
        } catch (ParseException e) {
168
            LOG.log(Level.WARNING, null, e);
169
        }
175
        }
170
    }
176
    }
171
177
Lines 180-199 Link Here
180
    }
186
    }
181
187
182
    public @Override void cancel() {
188
    public @Override void cancel() {
183
        synchronized (this) {
189
        final HintsProvider p = pendingProvider;
184
            cancelled = true;
185
        }
186
        HintsProvider p = pendingProvider;
187
        if (p != null) {
190
        if (p != null) {
188
            p.cancel();
191
            p.cancel();
189
        }
192
        }
190
    }
193
    }
191
192
    private synchronized void resume() {
193
        cancelled = false;
194
    }
195
196
    private synchronized boolean isCancelled() {
197
        return cancelled;
198
    }
199
}
194
}
(-)a/csl.api/src/org/netbeans/modules/csl/hints/infrastructure/SuggestionsTask.java (-86 / +81 lines)
Lines 56-61 Link Here
56
import org.netbeans.modules.csl.api.Hint;
56
import org.netbeans.modules.csl.api.Hint;
57
import org.netbeans.modules.csl.api.OffsetRange;
57
import org.netbeans.modules.csl.api.OffsetRange;
58
import org.netbeans.modules.csl.api.RuleContext;
58
import org.netbeans.modules.csl.api.RuleContext;
59
import org.netbeans.modules.csl.core.SpiSupportAccessor;
59
import org.netbeans.modules.csl.spi.ParserResult;
60
import org.netbeans.modules.csl.spi.ParserResult;
60
import org.netbeans.modules.parsing.api.ParserManager;
61
import org.netbeans.modules.parsing.api.ParserManager;
61
import org.netbeans.modules.parsing.api.ResultIterator;
62
import org.netbeans.modules.parsing.api.ResultIterator;
Lines 66-71 Link Here
66
import org.netbeans.modules.parsing.spi.ParserResultTask;
67
import org.netbeans.modules.parsing.spi.ParserResultTask;
67
import org.netbeans.modules.parsing.spi.Scheduler;
68
import org.netbeans.modules.parsing.spi.Scheduler;
68
import org.netbeans.modules.parsing.spi.SchedulerEvent;
69
import org.netbeans.modules.parsing.spi.SchedulerEvent;
70
import org.netbeans.modules.parsing.spi.support.CancelSupport;
69
import org.netbeans.spi.editor.hints.ErrorDescription;
71
import org.netbeans.spi.editor.hints.ErrorDescription;
70
import org.netbeans.spi.editor.hints.HintsController;
72
import org.netbeans.spi.editor.hints.HintsController;
71
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileObject;
Lines 75-84 Link Here
75
 * 
77
 * 
76
 * @author Tor Norbye
78
 * @author Tor Norbye
77
 */
79
 */
78
public class SuggestionsTask extends ParserResultTask<ParserResult> {
80
public final class SuggestionsTask extends ParserResultTask<ParserResult> {
79
    
81
    
80
    private static final Logger LOG = Logger.getLogger(SuggestionsTask.class.getName());
82
    private static final Logger LOG = Logger.getLogger(SuggestionsTask.class.getName());
81
    private volatile boolean cancelled = false;
83
    private final CancelSupport cancel = CancelSupport.create(this);
82
84
83
    /**
85
    /**
84
     * Tracks the HintsProvider being executed, so it can be cancelled.
86
     * Tracks the HintsProvider being executed, so it can be cancelled.
Lines 89-183 Link Here
89
    }
91
    }
90
    
92
    
91
    public @Override void run(ParserResult result, SchedulerEvent event) {
93
    public @Override void run(ParserResult result, SchedulerEvent event) {
92
        resume();
94
93
        
94
        final FileObject fileObject = result.getSnapshot().getSource().getFileObject();
95
        final FileObject fileObject = result.getSnapshot().getSource().getFileObject();
95
        if (fileObject == null || isCancelled()) {
96
        if (fileObject == null || cancel.isCancelled()) {
96
            return;
97
            return;
97
        }
98
        }
98
99
99
        if (!(event instanceof CursorMovedSchedulerEvent) || isCancelled()) {
100
        if (!(event instanceof CursorMovedSchedulerEvent) || cancel.isCancelled()) {
100
            return;
101
            return;
101
        }
102
        }
102
103
103
        // Do we have a selection? If so, don't do suggestions
104
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
104
        CursorMovedSchedulerEvent evt = (CursorMovedSchedulerEvent) event;
105
        try {
105
        int[] range = new int [] {
106
            // Do we have a selection? If so, don't do suggestions
106
            Math.min(evt.getMarkOffset(), evt.getCaretOffset()),
107
            CursorMovedSchedulerEvent evt = (CursorMovedSchedulerEvent) event;
107
            Math.max(evt.getMarkOffset(), evt.getCaretOffset())
108
            int[] range = new int [] {
108
        };
109
                Math.min(evt.getMarkOffset(), evt.getCaretOffset()),
109
        if (range != null && range.length == 2 && range[0] != -1 && range[1] != -1 && range[0] != range[1]) {
110
                Math.max(evt.getMarkOffset(), evt.getCaretOffset())
110
            HintsController.setErrors(fileObject, SuggestionsTask.class.getName(), Collections.<ErrorDescription>emptyList());
111
            };
111
            return;
112
            if (range != null && range.length == 2 && range[0] != -1 && range[1] != -1 && range[0] != range[1]) {
112
        }
113
                HintsController.setErrors(fileObject, SuggestionsTask.class.getName(), Collections.<ErrorDescription>emptyList());
114
                return;
115
            }
113
116
114
        final int pos = evt.getCaretOffset();
117
            final int pos = evt.getCaretOffset();
115
        if (pos == -1 || isCancelled()) {
118
            if (pos == -1 || cancel.isCancelled()) {
116
            return;
119
                return;
117
        }
120
            }
118
        
119
        try {
120
            ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
121
                public @Override void run(ResultIterator resultIterator) throws Exception {
122
                    Parser.Result r = resultIterator.getParserResult(pos);
123
                    if(!(r instanceof ParserResult)) {
124
                        return ;
125
                    }
126
                    Language language = LanguageRegistry.getInstance().getLanguageByMimeType(r.getSnapshot().getMimeType());
127
                    if (language == null || isCancelled()) {
128
                        return;
129
                    }
130
121
131
                    HintsProvider provider = language.getHintsProvider();
122
            try {
132
                    if (provider == null || isCancelled()) {
123
                ParserManager.parse(Collections.singleton(result.getSnapshot().getSource()), new UserTask() {
133
                        return;
124
                    public @Override void run(ResultIterator resultIterator) throws Exception {
134
                    }
125
                        Parser.Result r = resultIterator.getParserResult(pos);
135
                    GsfHintsManager manager = language.getHintsManager();
126
                        if(!(r instanceof ParserResult)) {
136
                    if (manager == null || isCancelled()) {
127
                            return ;
137
                        return;
128
                        }
138
                    }
129
                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(r.getSnapshot().getMimeType());
139
                    RuleContext ruleContext = manager.createRuleContext((ParserResult) r, language, pos, -1, -1);
130
                        if (language == null || cancel.isCancelled()) {
140
                    if (ruleContext == null || isCancelled()) {
131
                            return;
141
                        return;
132
                        }
142
                    }
143
                    List<ErrorDescription> descriptions = new ArrayList<ErrorDescription>();
144
                    List<Hint> hints = new ArrayList<Hint>();
145
133
146
                    OffsetRange linerange = findLineBoundaries(resultIterator.getSnapshot().getText(), pos);
134
                        HintsProvider provider = language.getHintsProvider();
147
                    try {
135
                        if (provider == null || cancel.isCancelled()) {
148
                        synchronized (this) {
136
                            return;
149
                            pendingProvider = provider;
137
                        }
150
                            if (isCancelled()) {
138
                        GsfHintsManager manager = language.getHintsManager();
139
                        if (manager == null || cancel.isCancelled()) {
140
                            return;
141
                        }
142
                        RuleContext ruleContext = manager.createRuleContext((ParserResult) r, language, pos, -1, -1);
143
                        if (ruleContext == null || cancel.isCancelled()) {
144
                            return;
145
                        }
146
                        List<ErrorDescription> descriptions = new ArrayList<ErrorDescription>();
147
                        List<Hint> hints = new ArrayList<Hint>();
148
149
                        OffsetRange linerange = findLineBoundaries(resultIterator.getSnapshot().getText(), pos);
150
                        try {
151
                            synchronized (this) {
152
                                pendingProvider = provider;
153
                                if (cancel.isCancelled()) {
154
                                    return;
155
                                }
156
                            }
157
                            provider.computeSuggestions(manager, ruleContext, hints, pos);
158
                        } finally {
159
                            pendingProvider = null;
160
                        }
161
162
                        for (int i = 0; i < hints.size(); i++) {
163
                            Hint hint = hints.get(i);
164
                            if (cancel.isCancelled()) {
151
                                return;
165
                                return;
152
                            }
166
                            }
167
                            // #224654 - suggestions may be returned for text unrelated to caret position
168
                            if (linerange != OffsetRange.NONE && !overlaps(linerange, hint.getRange())) {
169
                                continue;
170
                            }
171
                            ErrorDescription desc = manager.createDescription(hint, ruleContext, false, i == hints.size()-1);
172
                            descriptions.add(desc);
153
                        }
173
                        }
154
                        provider.computeSuggestions(manager, ruleContext, hints, pos);                        
155
                    } finally {
156
                        pendingProvider = null;
157
                    }
158
174
159
                    for (int i = 0; i < hints.size(); i++) {
175
                        if (cancel.isCancelled()) {
160
                        Hint hint = hints.get(i);
161
                        if (isCancelled()) {
162
                            return;
176
                            return;
163
                        }
177
                        }
164
                        // #224654 - suggestions may be returned for text unrelated to caret position
178
165
                        if (linerange != OffsetRange.NONE && !overlaps(linerange, hint.getRange())) {
179
                        HintsController.setErrors(r.getSnapshot().getSource().getFileObject(), SuggestionsTask.class.getName(), descriptions);
166
                            continue;
167
                        }
168
                        ErrorDescription desc = manager.createDescription(hint, ruleContext, false, i == hints.size()-1);
169
                        descriptions.add(desc);
170
                    }
180
                    }
171
181
                });
172
                    if (isCancelled()) {
182
            } catch (ParseException e) {
173
                        return;
183
                LOG.log(Level.WARNING, null, e);
174
                    }
184
            }
175
185
        } finally {
176
                    HintsController.setErrors(r.getSnapshot().getSource().getFileObject(), SuggestionsTask.class.getName(), descriptions);
186
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
177
                }
178
            });
179
        } catch (ParseException e) {
180
            LOG.log(Level.WARNING, null, e);
181
        }
187
        }
182
    }
188
    }
183
    
189
    
Lines 215-234 Link Here
215
    }
221
    }
216
222
217
    public @Override void cancel() {
223
    public @Override void cancel() {
218
        synchronized (this) {
224
        final HintsProvider p = pendingProvider;
219
            cancelled = true;
220
        }
221
        HintsProvider p = pendingProvider;
222
        if (p != null) {
225
        if (p != null) {
223
            p.cancel();
226
            p.cancel();
224
        }
227
        }
225
    }
228
    }
226
227
    private synchronized void resume() {
228
        cancelled = false;
229
    }
230
231
    private synchronized boolean isCancelled() {
232
        return cancelled;
233
    }
234
}
229
}
(-)a/csl.api/src/org/netbeans/modules/csl/navigation/BreadCrumbsTask.java (-30 / +39 lines)
Lines 80-85 Link Here
80
 */
80
 */
81
public class BreadCrumbsTask extends ElementScanningTask {
81
public class BreadCrumbsTask extends ElementScanningTask {
82
82
83
    public BreadCrumbsTask() {
84
    }
85
83
    private static final RequestProcessor WORKER = new RequestProcessor(BreadCrumbsTask.class.getName(), 1, false, false);
86
    private static final RequestProcessor WORKER = new RequestProcessor(BreadCrumbsTask.class.getName(), 1, false, false);
84
    
87
    
85
    @Override
88
    @Override
Lines 95-130 Link Here
95
    private final AtomicLong requestId = new AtomicLong();
98
    private final AtomicLong requestId = new AtomicLong();
96
    
99
    
97
    @Override
100
    @Override
98
    public void run(ParserResult result, SchedulerEvent event) {
101
    public void run(final ParserResult result, final SchedulerEvent event) {
99
        final long id = requestId.incrementAndGet();
102
        runWithCancelService(new Runnable() {
100
        
103
            @Override
101
        final Document doc = result.getSnapshot().getSource().getDocument(false);
104
            public void run() {
102
        
105
                resume();
103
        if (doc == null || !BreadcrumbsController.areBreadCrumsEnabled(doc)) return ;
106
                final long id = requestId.incrementAndGet();
104
        
107
105
        final int caret;
108
                final Document doc = result.getSnapshot().getSource().getDocument(false);
106
        
109
107
        if (event instanceof CursorMovedSchedulerEvent) {
110
                if (doc == null || !BreadcrumbsController.areBreadCrumsEnabled(doc)) return ;
108
            caret = ((CursorMovedSchedulerEvent) event).getCaretOffset();
111
109
        } else {
112
                final int caret;
110
            //XXX: outside AWT!
113
111
            JTextComponent c = EditorRegistry.focusedComponent();
114
                if (event instanceof CursorMovedSchedulerEvent) {
112
            
115
                    caret = ((CursorMovedSchedulerEvent) event).getCaretOffset();
113
            if (c != null && c.getDocument() == doc)
116
                } else {
114
                caret = c.getCaretPosition();
117
                    //XXX: outside AWT!
115
            else
118
                    JTextComponent c = EditorRegistry.focusedComponent();
116
                caret = (-1);
119
117
        }
120
                    if (c != null && c.getDocument() == doc)
118
        
121
                        caret = c.getCaretPosition();
119
        if (caret == (-1)) return ;
122
                    else
120
        
123
                        caret = (-1);
121
        final StructureItem structureRoot = computeStructureRoot(result.getSnapshot().getSource());
124
                }
122
        
125
123
        if (structureRoot == null) return ;
126
                if (caret == (-1)) return ;
124
        
127
125
        WORKER.post(new Runnable() {
128
                final StructureItem structureRoot = computeStructureRoot(result.getSnapshot().getSource());
126
            @Override public void run() {
129
127
                selectNode(doc, structureRoot, id, caret);
130
                if (structureRoot == null) return ;
131
132
                WORKER.post(new Runnable() {
133
                    @Override public void run() {
134
                        selectNode(doc, structureRoot, id, caret);
135
                    }
136
                });
128
            }
137
            }
129
        });
138
        });
130
    }
139
    }
(-)a/csl.api/src/org/netbeans/modules/csl/navigation/CaretListeningTask.java (-23 / +17 lines)
Lines 44-51 Link Here
44
44
45
package org.netbeans.modules.csl.navigation;
45
package org.netbeans.modules.csl.navigation;
46
46
47
import org.netbeans.modules.csl.core.SpiSupportAccessor;
47
import org.netbeans.modules.csl.spi.ParserResult;
48
import org.netbeans.modules.csl.spi.ParserResult;
48
import org.netbeans.modules.parsing.spi.*;
49
import org.netbeans.modules.parsing.spi.*;
50
import org.netbeans.modules.parsing.spi.support.CancelSupport;
49
51
50
/**
52
/**
51
 * This file is originally from Retouche, the Java Support
53
 * This file is originally from Retouche, the Java Support
Lines 56-98 Link Here
56
 * This task is called every time the caret position changes in a GSF editor.
58
 * This task is called every time the caret position changes in a GSF editor.
57
 * It delegates to the navigator to show the current selection.
59
 * It delegates to the navigator to show the current selection.
58
 */
60
 */
59
public class CaretListeningTask extends IndexingAwareParserResultTask<ParserResult> {
61
public final class CaretListeningTask extends IndexingAwareParserResultTask<ParserResult> {
60
    
62
    
61
    private boolean canceled;
63
    private final CancelSupport cancel = CancelSupport.create(this);
62
    
64
    
63
    CaretListeningTask() {
65
    CaretListeningTask() {
64
        super(TaskIndexingMode.ALLOWED_DURING_SCAN);
66
        super(TaskIndexingMode.ALLOWED_DURING_SCAN);
65
    }
67
    }
66
    
68
    
67
    public @Override void run(ParserResult result, SchedulerEvent event) {
69
    public @Override void run(ParserResult result, SchedulerEvent event) {
68
        resume();
70
69
        
70
        boolean navigatorShouldUpdate = ClassMemberPanel.getInstance() != null; // XXX set by navigator visible
71
        boolean navigatorShouldUpdate = ClassMemberPanel.getInstance() != null; // XXX set by navigator visible
71
        
72
        if (cancel.isCancelled() || (!navigatorShouldUpdate) || !(event instanceof CursorMovedSchedulerEvent)) {
72
        if (isCancelled() || (!navigatorShouldUpdate) || !(event instanceof CursorMovedSchedulerEvent)) {
73
            return;
73
            return;
74
        }
74
        }
75
        
75
76
        int offset = ((CursorMovedSchedulerEvent) event).getCaretOffset();
76
        SpiSupportAccessor.getInstance().setCancelSupport(cancel);
77
        if (offset != -1) {
77
        try {
78
            ClassMemberPanel.getInstance().selectElement(result, offset);
78
            int offset = ((CursorMovedSchedulerEvent) event).getCaretOffset();
79
            if (offset != -1) {
80
                ClassMemberPanel.getInstance().selectElement(result, offset);
81
            }
82
        } finally {
83
            SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
79
        }
84
        }
80
    }
85
    }
81
86
82
    /**
87
83
     * After this method is called the task if running should exit the run
88
    @Override
84
     * method immediately.
85
     */
86
    public final synchronized void cancel() {
89
    public final synchronized void cancel() {
87
        canceled = true;
88
    }
89
    
90
    protected final synchronized boolean isCancelled() {
91
        return canceled;
92
    }
93
    
94
    protected final synchronized void resume() {
95
        canceled = false;
96
    }
90
    }
97
91
98
    public @Override int getPriority() {
92
    public @Override int getPriority() {
(-)a/csl.api/src/org/netbeans/modules/csl/navigation/ClassMemberNavigatorSourceFactory.java (-5 / +14 lines)
Lines 48-59 Link Here
48
import java.util.Collections;
48
import java.util.Collections;
49
import org.netbeans.modules.csl.core.AbstractTaskFactory;
49
import org.netbeans.modules.csl.core.AbstractTaskFactory;
50
import org.netbeans.modules.csl.core.Language;
50
import org.netbeans.modules.csl.core.Language;
51
import org.netbeans.modules.csl.core.SpiSupportAccessor;
51
import org.netbeans.modules.parsing.api.Snapshot;
52
import org.netbeans.modules.parsing.api.Snapshot;
52
import org.netbeans.modules.parsing.spi.Scheduler;
53
import org.netbeans.modules.parsing.spi.Scheduler;
53
import org.netbeans.modules.parsing.spi.SchedulerTask;
54
import org.netbeans.modules.parsing.spi.SchedulerTask;
54
import org.openide.util.Lookup;
55
import org.openide.util.Lookup;
55
import org.netbeans.modules.csl.spi.ParserResult;
56
import org.netbeans.modules.csl.spi.ParserResult;
56
import org.netbeans.modules.parsing.spi.*;
57
import org.netbeans.modules.parsing.spi.*;
58
import org.netbeans.modules.parsing.spi.support.CancelSupport;
57
59
58
/**
60
/**
59
 * This file is originally from Retouche, the Java Support 
61
 * This file is originally from Retouche, the Java Support 
Lines 108-113 Link Here
108
    }
110
    }
109
111
110
    private final class ProxyElementScanningTask extends IndexingAwareParserResultTask<ParserResult> {
112
    private final class ProxyElementScanningTask extends IndexingAwareParserResultTask<ParserResult> {
113
        private final CancelSupport cancel = CancelSupport.create(this);
111
        private ElementScanningTask task = null;
114
        private ElementScanningTask task = null;
112
        private Class<? extends Scheduler> clazz;
115
        private Class<? extends Scheduler> clazz;
113
116
Lines 126-141 Link Here
126
        }
129
        }
127
130
128
        public @Override void cancel() {
131
        public @Override void cancel() {
129
            ElementScanningTask t = getTask();
132
            final ElementScanningTask t = getTask();
130
            if (t != null) {
133
            if (t != null) {
131
                t.cancel();
134
                t.cancel();
132
            }
135
            }
133
        }
136
        }
134
137
135
        public @Override void run(ParserResult result, SchedulerEvent event) {
138
        @Override
136
            ElementScanningTask t = getTask();
139
        public void run(ParserResult result, SchedulerEvent event) {
137
            if (t != null) {
140
            SpiSupportAccessor.getInstance().setCancelSupport(cancel);
138
                t.run(result, event);
141
            try {
142
                final ElementScanningTask t = getTask();
143
                if (t != null) {
144
                    t.run(result, event);
145
                }
146
            } finally {
147
                SpiSupportAccessor.getInstance().removeCancelSupport(cancel);
139
            }
148
            }
140
        }
149
        }
141
150
(-)a/csl.api/src/org/netbeans/modules/csl/navigation/ClassMemberPanelUI.java (-10 / +14 lines)
Lines 220-236 Link Here
220
            public @Override Class<? extends Scheduler> getSchedulerClass() {
220
            public @Override Class<? extends Scheduler> getSchedulerClass() {
221
                return CSLNavigatorScheduler.class;
221
                return CSLNavigatorScheduler.class;
222
            }
222
            }
223
            @Override public void run(ParserResult result, SchedulerEvent event) {
223
            @Override public void run(final ParserResult result, final SchedulerEvent event) {
224
                resume();
224
                runWithCancelService(new Runnable() {
225
                
225
                    @Override
226
                StructureItem root = computeStructureRoot(result.getSnapshot().getSource());
226
                    public void run() {
227
                FileObject file = result.getSnapshot().getSource().getFileObject();
227
                        resume();
228
                        StructureItem root = computeStructureRoot(result.getSnapshot().getSource());
229
                        FileObject file = result.getSnapshot().getSource().getFileObject();
228
230
229
                if (root != null && file != null) {
231
                        if (root != null && file != null) {
230
                    Document doc = result.getSnapshot().getSource().getDocument(false);
232
                            Document doc = result.getSnapshot().getSource().getDocument(false);
231
                    BaseDocument bd = doc instanceof BaseDocument ? (BaseDocument)doc : null;
233
                            BaseDocument bd = doc instanceof BaseDocument ? (BaseDocument)doc : null;
232
                    refresh(root, file, bd);
234
                            refresh(root, file, bd);
233
                }
235
                        }
236
                    }
237
                });
234
            }
238
            }
235
        };
239
        };
236
        
240
        
(-)a/csl.api/src/org/netbeans/modules/csl/navigation/ElementScanningTask.java (-8 / +20 lines)
Lines 56-61 Link Here
56
import java.util.logging.Level;
56
import java.util.logging.Level;
57
import java.util.logging.Logger;
57
import java.util.logging.Logger;
58
import javax.swing.ImageIcon;
58
import javax.swing.ImageIcon;
59
import org.netbeans.api.annotations.common.NonNull;
59
import org.netbeans.api.editor.mimelookup.MimePath;
60
import org.netbeans.api.editor.mimelookup.MimePath;
60
import org.netbeans.modules.csl.api.StructureScanner;
61
import org.netbeans.modules.csl.api.StructureScanner;
61
import org.netbeans.modules.csl.api.ElementHandle;
62
import org.netbeans.modules.csl.api.ElementHandle;
Lines 65-70 Link Here
65
import org.netbeans.modules.csl.core.Language;
66
import org.netbeans.modules.csl.core.Language;
66
import org.netbeans.modules.csl.core.LanguageRegistry;
67
import org.netbeans.modules.csl.core.LanguageRegistry;
67
import org.netbeans.modules.csl.api.HtmlFormatter;
68
import org.netbeans.modules.csl.api.HtmlFormatter;
69
import org.netbeans.modules.csl.core.SpiSupportAccessor;
68
import org.netbeans.modules.csl.navigation.ElementNode.Description;
70
import org.netbeans.modules.csl.navigation.ElementNode.Description;
69
import org.netbeans.modules.csl.spi.ParserResult;
71
import org.netbeans.modules.csl.spi.ParserResult;
70
import org.netbeans.modules.parsing.api.Embedding;
72
import org.netbeans.modules.parsing.api.Embedding;
Lines 75-80 Link Here
75
import org.netbeans.modules.parsing.api.UserTask;
77
import org.netbeans.modules.parsing.api.UserTask;
76
import org.netbeans.modules.parsing.spi.*;
78
import org.netbeans.modules.parsing.spi.*;
77
import org.netbeans.modules.parsing.spi.Parser.Result;
79
import org.netbeans.modules.parsing.spi.Parser.Result;
80
import org.netbeans.modules.parsing.spi.support.CancelSupport;
78
import org.openide.filesystems.FileObject;
81
import org.openide.filesystems.FileObject;
79
import org.openide.util.ImageUtilities;
82
import org.openide.util.ImageUtilities;
80
import org.openide.util.RequestProcessor;
83
import org.openide.util.RequestProcessor;
Lines 94-107 Link Here
94
public abstract class ElementScanningTask extends IndexingAwareParserResultTask<ParserResult> {
97
public abstract class ElementScanningTask extends IndexingAwareParserResultTask<ParserResult> {
95
98
96
    private static final Logger LOG = Logger.getLogger(ElementScanningTask.class.getName());
99
    private static final Logger LOG = Logger.getLogger(ElementScanningTask.class.getName());
97
    
100
98
    private boolean canceled;
101
    private final CancelSupport cs = CancelSupport.create(this);
102
    private volatile boolean canceled;
99
    
103
    
100
    /**
104
    /**
101
     * Reference to the last result of parsing processed into structure.
105
     * Reference to the last result of parsing processed into structure.
102
     */
106
     */
103
    private static final Map<Snapshot, Reference<ResultStructure>> lastResults = 
107
    private static final Map<Snapshot, Reference<ResultStructure>> lastResults = new WeakHashMap<>();
104
            new WeakHashMap<Snapshot, Reference<ResultStructure>>();
105
108
106
    /**
109
    /**
107
     * Cache the parser result and the resulting structure.
110
     * Cache the parser result and the resulting structure.
Lines 249-266 Link Here
249
        return new RootStructureItem(items);
252
        return new RootStructureItem(items);
250
    }
253
    }
251
254
252
    public @Override synchronized void cancel() {
255
    @Override
256
    public void cancel() {
253
        canceled = true;
257
        canceled = true;
254
    }
258
    }
255
259
256
    public synchronized void resume() {
260
    protected final void resume() {
257
        canceled = false;
261
        canceled = false;
258
    }
262
    }
259
263
260
    public synchronized boolean isCancelled() {
264
    protected final boolean isCancelled() {
261
        return canceled;
265
        return canceled;
262
    }
266
    }
263
    
267
268
    protected final void runWithCancelService(@NonNull final Runnable r) {
269
        SpiSupportAccessor.getInstance().setCancelSupport(cs);
270
        try {
271
272
        } finally {
273
            SpiSupportAccessor.getInstance().removeCancelSupport(cs);
274
        }
275
    }
264
    private static final class RootStructureItem implements StructureItem {
276
    private static final class RootStructureItem implements StructureItem {
265
277
266
        private final List<? extends StructureItem> items;
278
        private final List<? extends StructureItem> items;
(-)a/csl.api/src/org/netbeans/modules/csl/spi/support/CancelSupport.java (+111 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2015 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.csl.spi.support;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.modules.csl.core.SpiSupportAccessor;
46
import org.netbeans.modules.parsing.spi.SchedulerTask;
47
import org.openide.util.Parameters;
48
49
/**
50
 * Provides a thread safe testing of the {@link SchedulerTask} canceling.
51
 * Provides a thread safe testing of the {@link SchedulerTask} canceling for CSL
52
 * services which are not implemented using {@link SchedulerTask}. For {@link SchedulerTask}
53
 * subclasses use parsing api {@link org.netbeans.modules.parsing.spi.support.CancelSupport}
54
 * @author Tomas Zezula
55
 * @since 2.50
56
 */
57
public final class CancelSupport {
58
59
    private static final CancelSupport INSTANCE = new CancelSupport();
60
61
    static {
62
        SpiSupportAccessor.setInstance(new SpiSupportAccessorImpl());
63
    }
64
65
    private final ThreadLocal<org.netbeans.modules.parsing.spi.support.CancelSupport> selfSpi;
66
67
    private CancelSupport() {
68
        this.selfSpi = new ThreadLocal<>();
69
    }
70
71
    /**
72
     * Returns true if the task is canceled.
73
     * @return true when task is canceled
74
     */
75
    public boolean isCancelled() {
76
        final org.netbeans.modules.parsing.spi.support.CancelSupport spi = selfSpi.get();
77
        return spi == null ?
78
                false :
79
                spi.isCancelled();
80
    }
81
82
    /**
83
     * Returns the {@link CancelSupport} instance.
84
     * @return the {@link CancelSupport} instance.
85
     */
86
    @NonNull
87
    public static CancelSupport getDefault() {
88
        return INSTANCE;
89
    }
90
91
    private static final class SpiSupportAccessorImpl extends SpiSupportAccessor {
92
93
        @Override
94
        public void setCancelSupport(@NonNull final org.netbeans.modules.parsing.spi.support.CancelSupport cancelSupport) {
95
            Parameters.notNull("cancelSupport", cancelSupport); //NOI18N
96
            final CancelSupport cs = getDefault();
97
            if (cs.selfSpi.get() == null) {
98
                cs.selfSpi.set(cancelSupport);
99
            }
100
        }
101
102
        @Override
103
        public void removeCancelSupport(@NonNull final org.netbeans.modules.parsing.spi.support.CancelSupport cancelSupport) {
104
            Parameters.notNull("cancelSupport", cancelSupport); //NOI18N
105
            final CancelSupport cs = getDefault();
106
            if (cs.selfSpi.get() == cancelSupport) {
107
                cs.selfSpi.remove();
108
            }
109
        }
110
    }
111
}

Return to bug 241009