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 247161
Collapse All | Expand All

(-)a/parsing.api/apichanges.xml (+62 lines)
Lines 110-115 Link Here
110
<!-- ACTUAL CHANGES BEGIN HERE: -->
110
<!-- ACTUAL CHANGES BEGIN HERE: -->
111
111
112
  <changes>
112
  <changes>
113
      <change id="Source.Context.Lookup">
114
          <api name="ParsingAPI"/>
115
          <summary>Source provides access to Lookup</summary>
116
          <version major="9" minor="2"/>
117
          <date day="18" month="6" year="2014"/>
118
          <author login="sdedic"/>
119
          <compatibility source="compatible" binary="compatible" addition="yes"/>
120
          <description>
121
              <p>
122
                  In the presence of multiple scopes or users, the parsing system needs
123
                  to access the proper context even though the work is done by different 
124
                  threads. It also has to propagate the proper context back to the user
125
                  tasks.
126
              </p>
127
              <p>
128
                  Source can now be created with a Lookup that provides such proper context,
129
                  or automatically uses Lookup.getDefault if no explicit Lookup is given.
130
              </p>
131
          </description>
132
          <issue number="247161"/>
133
      </change>
134
    <change id="Parsing.Netbeans.Cleanup">
135
          <api name="ParsingAPI"/>
136
          <summary>Parsing API cleaned up from IDE dependencies</summary>
137
          <version major="9" minor="1"/>
138
          <date day="6" month="5" year="2014"/>
139
          <author login="sdedic"/>
140
          <compatibility source="compatible" binary="compatible" semantic="incompatible" modification="yes"/>
141
          <description>
142
              <p>
143
                The Parsing API dependended on Windows System, Editor Registry, Data Systems and other IDE artifacts. All those
144
                dependencies were externalized as 'private SPIs' in the package <code>org.netbeans.modules.parsing.impspi</code>.
145
                The implementation that uses the other NetBeans IDE APIs resides in module <code>parsing.nb</code>.
146
                No API change was done, but the execution now relies on a proper binding to be present in the running application
147
                or a testsuite.
148
              </p>
149
              <p>
150
                Basic testing environment was provided in unit tests, which implements basic of the externalized functions. However
151
                if a test need to check reparsing after document change, or data object change. Full implementation may be needed -
152
                the implementor can use a <code>test-dependency</code> to the <code>org.netbeans.modules.parsing.nb</code> module.
153
              </p>
154
          </description>
155
      </change>
156
      <change id="Separate.Parsing.Indexing">
157
          <api name="ParsingAPI"/>
158
          <summary>Indexing API separated to its own module</summary>
159
          <version major="9" minor="0"/>
160
          <date day="20" month="4" year="2014"/>
161
          <author login="sdedic"/>
162
          <compatibility source="incompatible" binary="compatible" semantic="compatible" modification="yes"/>
163
          <description>
164
              <p>
165
                  Historically the module offered both APIs for Parsing (invoking parser, implementing parser) and
166
                  Indexing (refresh index, index SPIs). Those APIs are typically used by unrelated pieces of code,
167
                  possibly with the exception of "refresh" actions.
168
              </p>
169
              <p>
170
                  The indexing now resides separately in its <code>parsing.indexing</code> module. Binary compatibility
171
                  is kept by using module-auto-deps.xml.
172
              </p>
173
          </description>
174
      </change>
113
      <change id="SuspendStatus.isSuspendSupported">
175
      <change id="SuspendStatus.isSuspendSupported">
114
          <api name="ParsingAPI"/>
176
          <api name="ParsingAPI"/>
115
          <summary>Added <code>SuspendStatus.isSuspendSupported</code></summary>
177
          <summary>Added <code>SuspendStatus.isSuspendSupported</code></summary>
(-)a/parsing.api/manifest.mf (-1 lines)
Lines 1-7 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.parsing.api/1
2
OpenIDE-Module: org.netbeans.modules.parsing.api/1
3
OpenIDE-Module-Implementation-Version: 8
3
OpenIDE-Module-Implementation-Version: 8
4
OpenIDE-Module-Install: org/netbeans/modules/parsing/impl/Installer.class
5
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/parsing/impl/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/parsing/impl/Bundle.properties
6
OpenIDE-Module-Layer: org/netbeans/modules/parsing/impl/layer.xml
5
OpenIDE-Module-Layer: org/netbeans/modules/parsing/impl/layer.xml
7
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Show-In-Client: false
(-)a/parsing.api/module-auto-deps.xml (+63 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
6
7
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
8
Other names may be trademarks of their respective owners.
9
10
11
The contents of this file are subject to the terms of either the GNU
12
General Public License Version 2 only ("GPL") or the Common
13
Development and Distribution License("CDDL") (collectively, the
14
"License"). You may not use this file except in compliance with the
15
License. You can obtain a copy of the License at
16
http://www.netbeans.org/cddl-gplv2.html
17
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
18
specific language governing permissions and limitations under the
19
License.  When distributing the software, include this License Header
20
Notice in each file and include the License file at
21
nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
22
particular file as subject to the "Classpath" exception as provided
23
by Oracle in the GPL Version 2 section of the License file that
24
accompanied this code. If applicable, add the following below the
25
License Header, with the fields enclosed by brackets [] replaced by
26
your own identifying information:
27
"Portions Copyrighted [year] [name of copyright owner]"
28
29
Contributor(s):
30
31
The Original Software is NetBeans. The Initial Developer of the Original
32
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
33
Microsystems, Inc. All Rights Reserved.
34
35
If you wish your version of this file to be governed by only the CDDL
36
or only the GPL Version 2, indicate your decision by adding
37
"[Contributor] elects to include this software in this distribution
38
under the [CDDL or GPL Version 2] license." If you do not indicate a
39
single choice of license, a recipient has the option to distribute
40
your version of this file under either the CDDL, the GPL Version 2 or
41
to extend the choice of license to its licensees as provided above.
42
However, if you add GPL Version 2 code and therefore, elected the GPL
43
Version 2 license, then the option applies only if the new code is
44
made subject to such option by the copyright holder.
45
-->
46
47
<!DOCTYPE transformations PUBLIC "-//NetBeans//DTD Module Automatic Dependencies 1.0//EN" "http://www.netbeans.org/dtds/module-auto-deps-1_0.dtd">
48
49
<transformations version="1.0">
50
    <transformationgroup>
51
        <description>Separation of Parsing and Indexing APIs</description>
52
        <transformation>
53
            <trigger-dependency type="older">
54
                <module-dependency codenamebase="org.netbeans.modules.parsing.api" major="1" spec="9.0"/>
55
            </trigger-dependency>
56
            <implies>
57
                <result>
58
                    <module-dependency codenamebase="org.netbeans.modules.parsing.indexing" spec="9.0"/>
59
                </result>
60
            </implies>
61
        </transformation>
62
    </transformationgroup>
63
</transformations>
(-)a/parsing.api/nbproject/project.properties (-1 / +1 lines)
Lines 3-9 Link Here
3
javac.source=1.7
3
javac.source=1.7
4
javadoc.apichanges=${basedir}/apichanges.xml
4
javadoc.apichanges=${basedir}/apichanges.xml
5
javadoc.arch=${basedir}/arch.xml
5
javadoc.arch=${basedir}/arch.xml
6
spec.version.base=1.78.0
6
spec.version.base=9.2.0
7
7
8
test.config.stableBTD.includes=**/*Test.class
8
test.config.stableBTD.includes=**/*Test.class
9
test.config.stableBTD.excludes=\
9
test.config.stableBTD.excludes=\
(-)a/parsing.api/nbproject/project.xml (-129 / +17 lines)
Lines 24-62 Link Here
24
                    </run-dependency>
24
                    </run-dependency>
25
                </dependency>
25
                </dependency>
26
                <dependency>
26
                <dependency>
27
                    <code-name-base>org.netbeans.api.progress</code-name-base>
27
                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
28
                    <build-prerequisite/>
28
                    <build-prerequisite/>
29
                    <compile-dependency/>
29
                    <compile-dependency/>
30
                    <run-dependency>
30
                    <run-dependency>
31
                        <release-version>1</release-version>
31
                        <specification-version>1.1</specification-version>
32
                        <specification-version>1.13</specification-version>
33
                    </run-dependency>
34
                </dependency>
35
                <dependency>
36
                    <code-name-base>org.netbeans.libs.lucene</code-name-base>
37
                    <build-prerequisite/>
38
                    <compile-dependency/>
39
                    <run-dependency>
40
                        <release-version>3</release-version>
41
                        <specification-version>3.0</specification-version>
42
                    </run-dependency>
43
                </dependency>
44
                <dependency>
45
                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
46
                    <build-prerequisite/>
47
                    <compile-dependency/>
48
                    <run-dependency>
49
                        <release-version>3</release-version>
50
                        <specification-version>3.1</specification-version>
51
                    </run-dependency>
52
                </dependency>
53
                <dependency>
54
                    <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
55
                    <build-prerequisite/>
56
                    <compile-dependency/>
57
                    <run-dependency>
58
                        <release-version>1</release-version>
59
                        <specification-version>1.13</specification-version>
60
                    </run-dependency>
32
                    </run-dependency>
61
                </dependency>
33
                </dependency>
62
                <dependency>
34
                <dependency>
Lines 69-83 Link Here
69
                    </run-dependency>
41
                    </run-dependency>
70
                </dependency>
42
                </dependency>
71
                <dependency>
43
                <dependency>
72
                    <code-name-base>org.netbeans.modules.editor.settings.storage</code-name-base>
73
                    <build-prerequisite/>
74
                    <compile-dependency/>
75
                    <run-dependency>
76
                        <release-version>1</release-version>
77
                        <specification-version>1.19</specification-version>
78
                    </run-dependency>
79
                </dependency>
80
                <dependency>
81
                    <code-name-base>org.netbeans.modules.editor.util</code-name-base>
44
                    <code-name-base>org.netbeans.modules.editor.util</code-name-base>
82
                    <build-prerequisite/>
45
                    <build-prerequisite/>
83
                    <compile-dependency/>
46
                    <compile-dependency/>
Lines 96-124 Link Here
96
                    </run-dependency>
59
                    </run-dependency>
97
                </dependency>
60
                </dependency>
98
                <dependency>
61
                <dependency>
99
                    <code-name-base>org.netbeans.modules.masterfs</code-name-base>
100
                    <build-prerequisite/>
101
                    <compile-dependency/>
102
                    <run-dependency>
103
                        <release-version>2</release-version>
104
                        <specification-version>2.25</specification-version>
105
                    </run-dependency>
106
                </dependency>
107
                <dependency>
108
                    <code-name-base>org.netbeans.modules.parsing.lucene</code-name-base>
62
                    <code-name-base>org.netbeans.modules.parsing.lucene</code-name-base>
109
                    <build-prerequisite/>
63
                    <build-prerequisite/>
110
                    <compile-dependency/>
64
                    <compile-dependency/>
111
                    <run-dependency>
65
                    <run-dependency>
112
                        <release-version>2</release-version>
66
                        <release-version>2</release-version>
113
                        <specification-version>2.24</specification-version>
67
                        <specification-version>2.28</specification-version>
114
                    </run-dependency>
115
                </dependency>
116
                <dependency>
117
                    <code-name-base>org.netbeans.modules.project.indexingbridge</code-name-base>
118
                    <build-prerequisite/>
119
                    <compile-dependency/>
120
                    <run-dependency>
121
                        <specification-version>1.5</specification-version>
122
                    </run-dependency>
68
                    </run-dependency>
123
                </dependency>
69
                </dependency>
124
                <dependency>
70
                <dependency>
Lines 131-145 Link Here
131
                    </run-dependency>
77
                    </run-dependency>
132
                </dependency>
78
                </dependency>
133
                <dependency>
79
                <dependency>
134
                    <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
135
                    <build-prerequisite/>
136
                    <compile-dependency/>
137
                    <run-dependency>
138
                        <release-version>1</release-version>
139
                        <specification-version>1.32</specification-version>
140
                    </run-dependency>
141
                </dependency>
142
                <dependency>
143
                    <code-name-base>org.netbeans.modules.queries</code-name-base>
80
                    <code-name-base>org.netbeans.modules.queries</code-name-base>
144
                    <build-prerequisite/>
81
                    <build-prerequisite/>
145
                    <compile-dependency/>
82
                    <compile-dependency/>
Lines 149-192 Link Here
149
                    </run-dependency>
86
                    </run-dependency>
150
                </dependency>
87
                </dependency>
151
                <dependency>
88
                <dependency>
152
                    <code-name-base>org.netbeans.modules.sampler</code-name-base>
153
                    <build-prerequisite/>
154
                    <compile-dependency/>
155
                    <run-dependency>
156
                        <specification-version>1.0</specification-version>
157
                    </run-dependency>
158
                </dependency>
159
                <dependency>
160
                    <code-name-base>org.netbeans.spi.tasklist</code-name-base>
161
                    <build-prerequisite/>
162
                    <compile-dependency/>
163
                    <run-dependency>
164
                        <release-version>1</release-version>
165
                        <specification-version>1.10</specification-version>
166
                    </run-dependency>
167
                </dependency>
168
                <dependency>
169
                    <code-name-base>org.openide.awt</code-name-base>
170
                    <build-prerequisite/>
171
                    <compile-dependency/>
172
                    <run-dependency>
173
                        <specification-version>7.25</specification-version>
174
                    </run-dependency>
175
                </dependency>
176
                <dependency>
177
                    <code-name-base>org.openide.filesystems</code-name-base>
89
                    <code-name-base>org.openide.filesystems</code-name-base>
178
                    <build-prerequisite/>
90
                    <build-prerequisite/>
179
                    <compile-dependency/>
91
                    <compile-dependency/>
180
                    <run-dependency>
92
                    <run-dependency>
181
                        <specification-version>7.61</specification-version>
93
                        <specification-version>9.0</specification-version>
182
                    </run-dependency>
183
                </dependency>
184
                <dependency>
185
                    <code-name-base>org.openide.loaders</code-name-base>
186
                    <build-prerequisite/>
187
                    <compile-dependency/>
188
                    <run-dependency>
189
                        <specification-version>6.9</specification-version>
190
                    </run-dependency>
94
                    </run-dependency>
191
                </dependency>
95
                </dependency>
192
                <dependency>
96
                <dependency>
Lines 198-224 Link Here
198
                    </run-dependency>
102
                    </run-dependency>
199
                </dependency>
103
                </dependency>
200
                <dependency>
104
                <dependency>
201
                    <code-name-base>org.openide.nodes</code-name-base>
105
                    <code-name-base>org.openide.util.base</code-name-base>
202
                    <build-prerequisite/>
106
                    <build-prerequisite/>
203
                    <compile-dependency/>
107
                    <compile-dependency/>
204
                    <run-dependency>
108
                    <run-dependency>
205
                        <specification-version>7.3</specification-version>
109
                        <specification-version>9.0</specification-version>
206
                    </run-dependency>
207
                </dependency>
208
                <dependency>
209
                    <code-name-base>org.openide.text</code-name-base>
210
                    <build-prerequisite/>
211
                    <compile-dependency/>
212
                    <run-dependency>
213
                        <specification-version>6.17</specification-version>
214
                    </run-dependency>
215
                </dependency>
216
                <dependency>
217
                    <code-name-base>org.openide.util</code-name-base>
218
                    <build-prerequisite/>
219
                    <compile-dependency/>
220
                    <run-dependency>
221
                        <specification-version>8.32</specification-version>
222
                    </run-dependency>
110
                    </run-dependency>
223
                </dependency>
111
                </dependency>
224
                <dependency>
112
                <dependency>
Lines 229-242 Link Here
229
                        <specification-version>8.0</specification-version>
117
                        <specification-version>8.0</specification-version>
230
                    </run-dependency>
118
                    </run-dependency>
231
                </dependency>
119
                </dependency>
232
                <dependency>
233
                    <code-name-base>org.openide.windows</code-name-base>
234
                    <build-prerequisite/>
235
                    <compile-dependency/>
236
                    <run-dependency>
237
                        <specification-version>6.20</specification-version>
238
                    </run-dependency>
239
                </dependency>
240
            </module-dependencies>
120
            </module-dependencies>
241
            <test-dependencies>
121
            <test-dependencies>
242
                <test-type>
122
                <test-type>
Lines 277-282 Link Here
277
                        <compile-dependency/>
157
                        <compile-dependency/>
278
                    </test-dependency>
158
                    </test-dependency>
279
                    <test-dependency>
159
                    <test-dependency>
160
                        <code-name-base>org.netbeans.modules.projectapi.nb</code-name-base>
161
                    </test-dependency>
162
                    <test-dependency>
280
                        <code-name-base>org.netbeans.modules.projectui</code-name-base>
163
                        <code-name-base>org.netbeans.modules.projectui</code-name-base>
281
                        <compile-dependency/>
164
                        <compile-dependency/>
282
                    </test-dependency>
165
                    </test-dependency>
Lines 290-303 Link Here
290
                        <compile-dependency/>
173
                        <compile-dependency/>
291
                        <test/>
174
                        <test/>
292
                    </test-dependency>
175
                    </test-dependency>
176
                    <!--                    <test-dependency>
177
                        <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
178
                        <compile-dependency/>
179
                        <test/>
180
                    </test-dependency>-->
181
                    <test-dependency>
182
                        <code-name-base>org.netbeans.api.progress.nb</code-name-base>
183
                    </test-dependency>
293
                </test-type>
184
                </test-type>
294
            </test-dependencies>
185
            </test-dependencies>
295
            <public-packages>
186
            <public-packages>
296
                <package>org.netbeans.modules.parsing.api</package>
187
                <package>org.netbeans.modules.parsing.api</package>
297
                <package>org.netbeans.modules.parsing.api.indexing</package>
298
                <package>org.netbeans.modules.parsing.spi</package>
188
                <package>org.netbeans.modules.parsing.spi</package>
299
                <package>org.netbeans.modules.parsing.spi.indexing</package>
300
                <package>org.netbeans.modules.parsing.spi.indexing.support</package>
301
                <package>org.netbeans.modules.parsing.spi.support</package>
189
                <package>org.netbeans.modules.parsing.spi.support</package>
302
            </public-packages>
190
            </public-packages>
303
        </data>
191
        </data>
(-)a/parsing.api/src/org/netbeans/modules/parsing/api/ParserManager.java (-16 / +65 lines)
Lines 43-50 Link Here
43
package org.netbeans.modules.parsing.api;
43
package org.netbeans.modules.parsing.api;
44
44
45
import java.lang.ref.Reference;
45
import java.lang.ref.Reference;
46
import java.lang.ref.ReferenceQueue;
47
import java.lang.ref.SoftReference;
48
import java.util.Collection;
46
import java.util.Collection;
49
import java.util.Collections;
47
import java.util.Collections;
50
import java.util.HashMap;
48
import java.util.HashMap;
Lines 52-61 Link Here
52
import java.util.Map;
50
import java.util.Map;
53
import java.util.concurrent.Future;
51
import java.util.concurrent.Future;
54
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NonNull;
55
53
import org.netbeans.api.editor.document.EditorMimeTypes;
56
import org.netbeans.api.editor.mimelookup.MimeLookup;
54
import org.netbeans.api.editor.mimelookup.MimeLookup;
57
import org.netbeans.modules.parsing.impl.*;
55
import org.netbeans.modules.parsing.impl.*;
58
import org.netbeans.modules.parsing.lucene.support.LowMemoryWatcher;
56
import org.netbeans.modules.parsing.spi.LowMemoryWatcher;
59
import org.netbeans.modules.parsing.spi.ParseException;
57
import org.netbeans.modules.parsing.spi.ParseException;
60
import org.netbeans.modules.parsing.spi.Parser;
58
import org.netbeans.modules.parsing.spi.Parser;
61
import org.netbeans.modules.parsing.spi.ParserFactory;
59
import org.netbeans.modules.parsing.spi.ParserFactory;
Lines 390-411 Link Here
390
    }
388
    }
391
389
392
    private static Parser findParser (final String mimeType) {
390
    private static Parser findParser (final String mimeType) {
393
        Parser p = null;
391
        return Utilities.getEnvFactory().findMimeParser(Lookup.getDefault(), mimeType);
394
        final Reference<Parser> ref = cachedParsers.get (mimeType);
392
    }
395
        if (ref != null) {
393
    
396
            p = ref.get();
394
    /**
395
     * Determines if the current execution is already called from the parsing
396
     * system. If code is called by the parser, it should avoid blocking on a lock
397
     * and must avoid blocking on other parsing results.
398
     * 
399
     * @return true, if the current thread executes code called from within the parser
400
     * @since 9.2
401
     */
402
    public static boolean isParsing() {
403
        return Utilities.holdsParserLock();
404
    }
405
406
    /**
407
     * Determines if the MIME type can be parsed. Rejects unknown MIME types (must be amongst {@link #getAllMimeTypes}.
408
     * Then accepts only text/* MIME type and specific hardcoded application/ MIME types.
409
     * 
410
     * @param mimeType the MIME type to check
411
     * @return true, if the MIME type can be parsed.
412
     * @since 9.2
413
     */
414
    public static boolean canBeParsed(String mimeType) {
415
        if (mimeType == null ||
416
            "content/unknown".equals(mimeType) ||    //NOI18N
417
            !EditorMimeTypes.getDefault().getSupportedMimeTypes().contains(mimeType)) {
418
            return false;
397
        }
419
        }
398
        if (p == null) {
420
399
            final Lookup lookup = MimeLookup.getLookup (mimeType);
421
        int slashIdx = mimeType.indexOf('/'); //NOI18N
400
            final ParserFactory parserFactory = lookup.lookup (ParserFactory.class);
422
        assert slashIdx != -1 : "Invalid mimetype: '" + mimeType + "'"; //NOI18N
401
            if (parserFactory == null) {
423
402
                throw new IllegalArgumentException("No parser for mime type: " + mimeType);
424
        String type = mimeType.substring(0, slashIdx);
425
        if (type.equals("application")) { //NOI18N
426
            if (!mimeType.equals("application/x-httpd-eruby") && !mimeType.equals("application/xml-dtd")) { //NOI18N
427
                return false;
403
            }
428
            }
404
            p = parserFactory.createParser(Collections.<Snapshot>emptyList());
429
        } else if (!type.equals("text")) { //NOI18N
405
            cachedParsers.put(mimeType, new SoftReference<Parser>(p));
430
            return false;
406
        }
431
        }
407
        return p;
432
433
//            if (allLanguagesParsersCount == -1) {
434
//                Collection<? extends ParserFactory> allLanguagesParsers = MimeLookup.getLookup(MimePath.EMPTY).lookupAll(ParserFactory.class);
435
//                allLanguagesParsersCount = allLanguagesParsers.size();
436
//            }
437
//            Collection<? extends ParserFactory> parsers = MimeLookup.getLookup(mimeType).lookupAll(ParserFactory.class);
438
//            if (parsers.size() - allLanguagesParsersCount > 0) {
439
//                return true;
440
//            }
441
//
442
//            // Ideally we should check that there are EmbeddingProviders registered for the
443
//            // mimeType, but let's assume that if there are TaskFactories they are either
444
//            // ordinary scheduler tasks or EmbeddingProviders. The former would most likely
445
//            // mean that there is also a Parser and would have been caught in the previous check.
446
//            if (allLanguagesTasksCount == -1) {
447
//                Collection<? extends TaskFactory> allLanguagesTasks = MimeLookup.getLookup(MimePath.EMPTY).lookupAll(TaskFactory.class);
448
//                allLanguagesTasksCount = allLanguagesTasks.size();
449
//            }
450
//            Collection<? extends TaskFactory> tasks = MimeLookup.getLookup(mimeType).lookupAll(TaskFactory.class);
451
//            if (tasks.size() - allLanguagesTasksCount > 0) {
452
//                return true;
453
//            }
454
455
        return true;
408
    }
456
    }
457
    
409
    //where
458
    //where
410
    private static Map<String,Reference<Parser>> cachedParsers = new HashMap<String,Reference<Parser>>();    
459
    private static Map<String,Reference<Parser>> cachedParsers = new HashMap<String,Reference<Parser>>();    
411
}
460
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/api/Snapshot.java (-3 / +3 lines)
Lines 53-59 Link Here
53
import org.netbeans.api.lexer.Language;
53
import org.netbeans.api.lexer.Language;
54
import org.netbeans.api.lexer.TokenHierarchy;
54
import org.netbeans.api.lexer.TokenHierarchy;
55
import org.netbeans.api.lexer.TokenId;
55
import org.netbeans.api.lexer.TokenId;
56
import org.netbeans.modules.parsing.impl.Installer;
56
import org.netbeans.modules.parsing.impl.Utilities;
57
import org.openide.filesystems.FileObject;
57
import org.openide.filesystems.FileObject;
58
import org.openide.filesystems.FileUtil;
58
import org.openide.filesystems.FileUtil;
59
59
Lines 112-118 Link Here
112
        int[][]             currentToOriginal,
112
        int[][]             currentToOriginal,
113
        int[][]             originalToCurrent) {
113
        int[][]             originalToCurrent) {
114
        final int textLength = text.length();
114
        final int textLength = text.length();
115
        if (textLength > Installer.MAX_FILE_SIZE) {
115
        if (textLength > Utilities.getMaxFileSize()) {
116
            text = "";  //NOI18N
116
            text = "";  //NOI18N
117
            LOG.log(
117
            LOG.log(
118
                Level.WARNING,
118
                Level.WARNING,
Lines 123-129 Link Here
123
                        FileUtil.getFileDisplayName(source.getFileObject()),
123
                        FileUtil.getFileDisplayName(source.getFileObject()),
124
                    mimePath,
124
                    mimePath,
125
                    textLength,
125
                    textLength,
126
                    Installer.MAX_FILE_SIZE
126
                    Utilities.getMaxFileSize()
127
                });
127
                });
128
        }
128
        }
129
        return new Snapshot(
129
        return new Snapshot(
(-)a/parsing.api/src/org/netbeans/modules/parsing/api/Source.java (-78 / +200 lines)
Lines 73-97 Link Here
73
import org.netbeans.api.lexer.LanguagePath;
73
import org.netbeans.api.lexer.LanguagePath;
74
import org.netbeans.api.queries.FileEncodingQuery;
74
import org.netbeans.api.queries.FileEncodingQuery;
75
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
75
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
76
import org.netbeans.modules.parsing.impl.Installer;
76
import org.netbeans.modules.parsing.impl.ParserEventForward;
77
import org.netbeans.modules.parsing.impl.SchedulerAccessor;
77
import org.netbeans.modules.parsing.impl.SchedulerAccessor;
78
import org.netbeans.modules.parsing.impl.SourceAccessor;
78
import org.netbeans.modules.parsing.impl.SourceAccessor;
79
import org.netbeans.modules.parsing.impl.SourceCache;
79
import org.netbeans.modules.parsing.impl.SourceCache;
80
import org.netbeans.modules.parsing.impl.SourceFlags;
80
import org.netbeans.modules.parsing.impl.SourceFlags;
81
import org.netbeans.modules.parsing.impl.TaskProcessor;
81
import org.netbeans.modules.parsing.impl.TaskProcessor;
82
import org.netbeans.modules.parsing.impl.event.EventSupport;
82
import org.netbeans.modules.parsing.impl.Utilities;
83
import org.netbeans.modules.parsing.impl.indexing.Util;
83
import org.netbeans.modules.parsing.implspi.SchedulerControl;
84
import org.netbeans.modules.parsing.implspi.SourceControl;
85
import org.netbeans.modules.parsing.implspi.SourceEnvironment;
84
import org.netbeans.modules.parsing.spi.Parser;
86
import org.netbeans.modules.parsing.spi.Parser;
85
import org.netbeans.modules.parsing.spi.Scheduler;
87
import org.netbeans.modules.parsing.spi.Scheduler;
86
import org.netbeans.modules.parsing.spi.SchedulerEvent;
88
import org.netbeans.modules.parsing.spi.SchedulerEvent;
87
import org.netbeans.modules.parsing.spi.SourceModificationEvent;
89
import org.netbeans.modules.parsing.spi.SourceModificationEvent;
88
import org.openide.cookies.EditorCookie;
89
import org.openide.filesystems.FileObject;
90
import org.openide.filesystems.FileObject;
90
import org.openide.filesystems.FileUtil;
91
import org.openide.filesystems.FileUtil;
91
import org.openide.loaders.DataObject;
92
import org.openide.util.Lookup;
92
import org.openide.loaders.DataObjectNotFoundException;
93
import org.openide.util.Parameters;
93
import org.openide.util.Parameters;
94
import org.openide.util.UserQuestionException;
95
94
96
95
97
/**
96
/**
Lines 109-120 Link Here
109
 * calls for the same file or document will return two different <code>Source</code>
108
 * calls for the same file or document will return two different <code>Source</code>
110
 * instances if the first instance is garbage collected prior the second call.
109
 * instances if the first instance is garbage collected prior the second call.
111
 *
110
 *
111
 * <p>
112
 * The Source can be created with a {@link Lookup} instance. This Lookup should be used
113
 * by parsing system, or callback tasks to locate services, that depend on the execution
114
 * context (ie which user is executing the task). Check the specific service's documentation 
115
 * on details of the service's context dependencies.
112
 * 
116
 * 
113
 * @author Jan Jancura
117
 * @author Jan Jancura
114
 * @author Tomas Zezula
118
 * @author Tomas Zezula
119
 * @since 9.2 implements Lookup.Provider
115
 */
120
 */
116
public final class Source {
121
public final class Source implements Lookup.Provider {
117
    
122
118
    /**
123
    /**
119
     * Gets a <code>Source</code> instance for a file. The <code>FileObject</code>
124
     * Gets a <code>Source</code> instance for a file. The <code>FileObject</code>
120
     * passed to this method has to be a valid data file. There is no <code>Source</code>
125
     * passed to this method has to be a valid data file. There is no <code>Source</code>
Lines 134-143 Link Here
134
            return null;
139
            return null;
135
        }
140
        }
136
        
141
        
137
        return _get(fileObject.getMIMEType(), fileObject);
142
        return _get(fileObject.getMIMEType(), fileObject, Lookup.getDefault());
138
    }
143
    }
139
    
144
    
140
    /**
145
    /**
146
     * Gets a <code>Source</code> instance for a file. The <code>FileObject</code>
147
     * passed to this method has to be a valid data file. There is no <code>Source</code>
148
     * representation for a folder.
149
     * <p/>
150
     * This form allows to specify Lookup that provides access to context-dependent
151
     * services for the parsing system and the user tasks called from parsing API.
152
     * 
153
     * @param fileObject The file to get <code>Source</code> for.
154
     * @param lkp The Lookup that provides the context
155
     * @return The <code>Source</code> for the given file or <code>null</code>
156
     *   if the file doesn't exist.
157
     * @since 9.2
158
     */
159
    public static Source create (
160
        FileObject          fileObject, Lookup lkp
161
    ) {
162
        Parameters.notNull("fileObject", fileObject); //NOI18N
163
        Parameters.notNull("lkp", lkp); //NOI18N
164
        if (!fileObject.isValid() || !fileObject.isData()) {
165
            return null;
166
        }
167
        
168
        return _get(fileObject.getMIMEType(), fileObject, lkp);
169
    }
170
171
    /**
141
     * Gets a <code>Source</code> instance for a <code>Document</code>. This method
172
     * Gets a <code>Source</code> instance for a <code>Document</code>. This method
142
     * is consistent with {@link #create(org.openide.filesystems.FileObject)} in the way
173
     * is consistent with {@link #create(org.openide.filesystems.FileObject)} in the way
143
     * that they both will return the same <code>Source</code> instance for
174
     * that they both will return the same <code>Source</code> instance for
Lines 171-176 Link Here
171
    public static Source create (
202
    public static Source create (
172
        Document            document
203
        Document            document
173
    ) {
204
    ) {
205
        return create(document, Lookup.getDefault());
206
    }
207
    
208
    /**
209
     * Gets a <code>Source</cide> instance for a <code>Document</code>. For details, please 
210
     * see {@link #create(javax.swing.text.Document)}; this form allows to specify
211
     * a Lookup that provides access to user or context-dependent services.
212
     * 
213
     * @param document the document to get <code>Source</code> for
214
     * @param lkp the context for the source
215
     * @return the Source instance
216
     * @see #create(javax.swing.text.Document) 
217
     * @since 9.2
218
     */
219
    public static Source create (
220
        Document            document, Lookup lkp
221
    ) {
174
        Parameters.notNull("document", document); //NOI18N
222
        Parameters.notNull("document", document); //NOI18N
175
223
176
        String mimeType = DocumentUtilities.getMimeType(document);
224
        String mimeType = DocumentUtilities.getMimeType(document);
Lines 190-210 Link Here
190
            }
238
            }
191
            
239
            
192
            if (source == null) {
240
            if (source == null) {
193
                FileObject fileObject = Util.getFileObject(document);
241
                FileObject fileObject = Utilities.getFileObject(document);
194
                if (fileObject != null) {
242
                if (fileObject != null) {
195
                    source = Source._get(mimeType, fileObject);
243
                    source = Source._get(mimeType, fileObject, lkp);
196
                } else {
244
                } else {
197
                    if ("text/x-dialog-binding".equals(mimeType)) { //NOI18N
245
                    if ("text/x-dialog-binding".equals(mimeType)) { //NOI18N
198
                        InputAttributes attributes = (InputAttributes) document.getProperty(InputAttributes.class);
246
                        InputAttributes attributes = (InputAttributes) document.getProperty(InputAttributes.class);
199
                        LanguagePath path = LanguagePath.get(MimeLookup.getLookup(mimeType).lookup(Language.class));
247
                        LanguagePath path = LanguagePath.get(MimeLookup.getLookup(mimeType).lookup(Language.class));
200
                        Document doc = (Document) attributes.getValue(path, "dialogBinding.document"); //NOI18N
248
                        Document doc = (Document) attributes.getValue(path, "dialogBinding.document"); //NOI18N
201
                        if (doc != null) {
249
                        if (doc != null) {
202
                            fileObject = Util.getFileObject(doc);
250
                            fileObject = Utilities.getFileObject(doc);
203
                        } else {
251
                        } else {
204
                            fileObject = (FileObject) attributes.getValue(path, "dialogBinding.fileObject"); //NOI18N
252
                            fileObject = (FileObject) attributes.getValue(path, "dialogBinding.fileObject"); //NOI18N
205
                        }
253
                        }
206
                    }
254
                    }
207
                    source = new Source(mimeType, document, fileObject);
255
                    source = new Source(mimeType, document, fileObject, lkp);
208
                }
256
                }
209
                document.putProperty(Source.class, new WeakReference<Source>(source));
257
                document.putProperty(Source.class, new WeakReference<Source>(source));
210
            }
258
            }
Lines 254-284 Link Here
254
            }
302
            }
255
        }
303
        }
256
        if (document != null) return document;
304
        if (document != null) return document;
257
        EditorCookie ec = null;
305
        assert fileObject != null;
258
259
        try {
306
        try {
260
            DataObject dataObject = DataObject.find (fileObject);
307
            return sourceEnv.readDocument(fileObject, forceOpen);
261
            ec = dataObject.getLookup ().lookup (EditorCookie.class);
308
        } catch (IOException ioe) {
262
        } catch (DataObjectNotFoundException ex) {
309
            LOG.log (Level.WARNING, null, ioe);
263
            //DataobjectNotFoundException may happen in case of deleting opened file
310
            return null;
264
            //handled by returning null
265
        }
311
        }
266
267
        if (ec == null) return null;
268
        Document doc = ec.getDocument ();
269
        if (doc == null && forceOpen) {
270
            try {
271
                try {
272
                    doc = ec.openDocument ();
273
                } catch (UserQuestionException uqe) {
274
                    uqe.confirmed ();
275
                    doc = ec.openDocument ();
276
                }
277
            } catch (IOException ioe) {
278
                LOG.log (Level.WARNING, null, ioe);
279
            }
280
        }
281
        return doc;
282
    }
312
    }
283
    
313
    
284
    /**
314
    /**
Lines 329-335 Link Here
329
                // but they usually don't and this should be good enough for Snapshots.
359
                // but they usually don't and this should be good enough for Snapshots.
330
                try {
360
                try {
331
                    if (fileObject.isValid ()) {
361
                    if (fileObject.isValid ()) {
332
                        if (fileObject.getSize() <= Installer.MAX_FILE_SIZE) {
362
                        if (fileObject.getSize() <= Utilities.getMaxFileSize()) {
333
                            final InputStream is = fileObject.getInputStream ();
363
                            final InputStream is = fileObject.getInputStream ();
334
                            assert is != null : "FileObject.getInputStream() returned null for FileObject: " + FileUtil.getFileDisplayName(fileObject); //NOI18N
364
                            assert is != null : "FileObject.getInputStream() returned null for FileObject: " + FileUtil.getFileDisplayName(fileObject); //NOI18N
335
                            try {
365
                            try {
Lines 396-402 Link Here
396
                                new Object[]{
426
                                new Object[]{
397
                                    FileUtil.getFileDisplayName(fileObject),
427
                                    FileUtil.getFileDisplayName(fileObject),
398
                                    fileObject.getSize(),
428
                                    fileObject.getSize(),
399
                                    Installer.MAX_FILE_SIZE
429
                                    Utilities.getMaxFileSize()
400
                                });
430
                                });
401
                        }
431
                        }
402
                    }
432
                    }
Lines 480-485 Link Here
480
        SourceAccessor.setINSTANCE(new MySourceAccessor());
510
        SourceAccessor.setINSTANCE(new MySourceAccessor());
481
    }
511
    }
482
        
512
        
513
    private final Lookup context;
483
    private final String mimeType;
514
    private final String mimeType;
484
    private final FileObject fileObject;
515
    private final FileObject fileObject;
485
    private final Document document;
516
    private final Document document;
Lines 493-517 Link Here
493
    private Map<Class<? extends Scheduler>, SchedulerEvent> schedulerEvents;
524
    private Map<Class<? extends Scheduler>, SchedulerEvent> schedulerEvents;
494
    //GuardedBy(this)
525
    //GuardedBy(this)
495
    private SourceCache     cache;
526
    private SourceCache     cache;
496
    //GuardedBy(this)
527
    //GuardedBy(flags)
497
    private volatile long eventId;
528
    private volatile long eventId;
498
    //Changes handling
529
    private volatile boolean listeningOnChanges;
499
    private final EventSupport support = new EventSupport (this);
500
530
531
    /**
532
     * SourceEnvironment callback
533
     */
534
    private final SourceControl ctrl = new SourceControl(this);
535
    /**
536
     * Binding of source to its environment
537
     */
538
    private final SourceEnvironment sourceEnv;
539
    /**
540
     * Demultiplexes events from all parsers to SourceEnvironment.
541
     */
542
    private final ParserEventForward peFwd;
543
544
    @SuppressWarnings("LeakingThisInConstructor")
501
    private Source (
545
    private Source (
502
        String              mimeType,
546
        String              mimeType,
503
        Document            document,
547
        Document            document,
504
        FileObject          fileObject
548
        FileObject          fileObject,
549
        Lookup              context
505
    ) {
550
    ) {
506
        this.mimeType =     mimeType;
551
        this.mimeType =     mimeType;
507
        this.document =     document;
552
        this.document =     document;
508
        this.fileObject =   fileObject;
553
        this.fileObject =   fileObject;
554
        this.context =      context;
555
        this.peFwd = new ParserEventForward();
556
        this.sourceEnv = Utilities.createEnvironment(this, ctrl);
509
    }
557
    }
510
558
    
511
    @NonNull
559
    @NonNull
512
    private static Source _get(
560
    private static Source _get(
513
            @NonNull final String mimeType,
561
            @NonNull final String mimeType,
514
            @NonNull final FileObject fileObject) {
562
            @NonNull final FileObject fileObject, 
563
            @NonNull final Lookup context) {
515
        assert mimeType != null;
564
        assert mimeType != null;
516
        assert fileObject != null;
565
        assert fileObject != null;
517
566
Lines 519-548 Link Here
519
            final Reference<Source> sourceRef = instances.get(fileObject);
568
            final Reference<Source> sourceRef = instances.get(fileObject);
520
            Source source = sourceRef == null ? null : sourceRef.get();
569
            Source source = sourceRef == null ? null : sourceRef.get();
521
            if (source == null || !mimeType.equals(source.getMimeType())) {
570
            if (source == null || !mimeType.equals(source.getMimeType())) {
522
                source = new Source(mimeType, null, fileObject);
571
                source = new Source(mimeType, null, fileObject, context);
523
                instances.put(fileObject, new WeakReference<>(source));
572
                instances.put(fileObject, new WeakReference<>(source));
524
            }
573
            }
574
            assert source.context == context;
525
            return source;
575
            return source;
526
        }
576
        }
527
    }
577
    }
528
578
529
    private void assignListeners () {
579
    private void assignListeners () {
530
        boolean listen = !suppressListening.get();
580
        final boolean listen = !suppressListening.get();
531
        if (listen) {
581
        if (listen) {
532
            support.init();
582
            if (listeningOnChanges) {
583
                return;
584
            }
585
            synchronized (TaskProcessor.INTERNAL_LOCK) {
586
                if (listeningOnChanges) {
587
                    return;
588
                }
589
                try {
590
                    sourceEnv.activate();
591
                } finally {
592
                    listeningOnChanges = true;
593
                }
594
            }
533
        }
595
        }
534
    }
596
    }
535
597
598
    private void setFlags(final Set<SourceFlags> flags) {
599
        // synchronized because of eventId
600
        synchronized (flags) {
601
            this.flags.addAll(flags);
602
            eventId++;
603
        }
604
    }
605
606
    private void setSourceModification (boolean sourceChanged, int startOffset, int endOffset) {
607
        ASourceModificationEvent oldSourceModificationEvent;
608
        ASourceModificationEvent newSourceModificationEvent;
609
        do {
610
            oldSourceModificationEvent = sourceModificationEvent.get();
611
            boolean mergedChange = sourceChanged | (oldSourceModificationEvent == null ? false : oldSourceModificationEvent.sourceChanged());
612
            newSourceModificationEvent = new ASourceModificationEvent (this, mergedChange, startOffset, endOffset);                
613
        } while (!sourceModificationEvent.compareAndSet(oldSourceModificationEvent, newSourceModificationEvent));
614
    }
615
616
    private void mimeTypeMayChanged() {
617
        final FileObject file = getFileObject();
618
        if (file != null && !Objects.equals(getMimeType(), file.getMIMEType())) {
619
            synchronized (Source.class) {
620
                instances.remove(file);
621
            }
622
        }
623
    }
624
    
625
    private SourceCache getCache() {
626
        synchronized (TaskProcessor.INTERNAL_LOCK) {
627
            if (cache == null)
628
                cache = new SourceCache (this, null);
629
            return cache;
630
        }
631
    }
632
633
    @SuppressWarnings("AccessingNonPublicFieldOfAnotherObject") // accessing internals is accessor's job
536
    private static class MySourceAccessor extends SourceAccessor {
634
    private static class MySourceAccessor extends SourceAccessor {
537
        
635
        
538
        @Override
636
        @Override
539
        public void setFlags (final Source source, final Set<SourceFlags> flags)  {
637
        public void setFlags (final Source source, final Set<SourceFlags> flags)  {
540
            assert source != null;
638
            assert source != null;
541
            assert flags != null;
639
            assert flags != null;
542
            synchronized (source.flags) {
640
            source.setFlags(flags);
543
                source.flags.addAll(flags);
544
                source.eventId++;
545
            }
546
        }
641
        }
547
642
548
        @Override
643
        @Override
Lines 555-561 Link Here
555
        @Override
650
        @Override
556
        public boolean cleanFlag (final Source source, final SourceFlags flag) {
651
        public boolean cleanFlag (final Source source, final SourceFlags flag) {
557
            assert source != null;
652
            assert source != null;
558
            assert flag != null;            
653
            assert flag != null;  
559
            return source.flags.remove(flag);            
654
            return source.flags.remove(flag);            
560
        }
655
        }
561
656
Lines 585-590 Link Here
585
        }
680
        }
586
681
587
        @Override
682
        @Override
683
        public void revalidate(Source source, int delay) {
684
            source.ctrl.revalidate(delay);
685
        }
686
687
        @Override
588
        public boolean invalidate(Source source, long id, Snapshot snapshot) {
688
        public boolean invalidate(Source source, long id, Snapshot snapshot) {
589
            assert source != null;
689
            assert source != null;
590
            synchronized (TaskProcessor.INTERNAL_LOCK) {
690
            synchronized (TaskProcessor.INTERNAL_LOCK) {
Lines 594-602 Link Here
594
                else {
694
                else {
595
                    //The eventId and flags are bound
695
                    //The eventId and flags are bound
596
                    long eventId;
696
                    long eventId;
597
                    synchronized (source.flags) {
697
                    eventId = source.eventId;
598
                        eventId = source.eventId;
599
                    }
600
                    if (id != eventId) {
698
                    if (id != eventId) {
601
                        return false;
699
                        return false;
602
                    }
700
                    }
Lines 610-615 Link Here
610
                }
708
                }
611
            }
709
            }
612
        }
710
        }
711
712
        @Override
713
        public void attachScheduler(Source src, SchedulerControl sched, boolean attach) {
714
            src.sourceEnv.attachScheduler(sched, attach);
715
        }
613
        
716
        
614
        @Override
717
        @Override
615
        public Parser getParser(Source source) {
718
        public Parser getParser(Source source) {
Lines 636-644 Link Here
636
        }
739
        }
637
        
740
        
638
        @Override
741
        @Override
639
        public EventSupport getEventSupport (final Source source) {
742
        public SourceControl getEnvControl(final Source source) {
640
            assert source != null;
743
            assert source != null;
641
            return source.support;
744
            return source.ctrl;
745
        }
746
747
        @Override
748
        public SourceEnvironment getEnv(final Source source) {
749
            assert source != null;
750
            return source.sourceEnv;
642
        }
751
        }
643
752
644
        @Override
753
        @Override
Lines 650-673 Link Here
650
        @Override
759
        @Override
651
        public void setSourceModification (Source source, boolean sourceChanged, int startOffset, int endOffset) {
760
        public void setSourceModification (Source source, boolean sourceChanged, int startOffset, int endOffset) {
652
            assert source != null;
761
            assert source != null;
653
            ASourceModificationEvent oldSourceModificationEvent;
762
            source.setSourceModification(sourceChanged, startOffset, endOffset);
654
            ASourceModificationEvent newSourceModificationEvent;
655
            do {
656
                oldSourceModificationEvent = source.sourceModificationEvent.get();
657
                boolean mergedChange = sourceChanged | (oldSourceModificationEvent == null ? false : oldSourceModificationEvent.sourceChanged());
658
                newSourceModificationEvent = new ASourceModificationEvent (source, mergedChange, startOffset, endOffset);                
659
            } while (!source.sourceModificationEvent.compareAndSet(oldSourceModificationEvent, newSourceModificationEvent));
660
        }
763
        }
661
764
662
        @Override
765
        @Override
663
        public void mimeTypeMayChanged(@NonNull final Source source) {
766
        public void mimeTypeMayChanged(@NonNull final Source source) {
664
            assert source != null;
767
            assert source != null;
665
            final FileObject file = source.getFileObject();
768
            source.mimeTypeMayChanged();
666
            if (file != null && !Objects.equals(source.getMimeType(), file.getMIMEType())) {
667
                synchronized (Source.class) {
668
                    instances.remove(file);
669
                }
670
            }
671
        }
769
        }
672
770
673
        @Override
771
        @Override
Lines 735-745 Link Here
735
        @Override
833
        @Override
736
        public SourceCache getCache (final Source source) {
834
        public SourceCache getCache (final Source source) {
737
            assert source != null;
835
            assert source != null;
738
            synchronized (TaskProcessor.INTERNAL_LOCK) {
836
            return source.getCache();
739
                if (source.cache == null)
740
                    source.cache = new SourceCache (source, null);
741
                return source.cache;
742
            }
743
        }
837
        }
744
838
745
        @Override
839
        @Override
Lines 806-814 Link Here
806
            return origCache;
900
            return origCache;
807
        }
901
        }
808
902
903
        @Override
904
        @NonNull
905
        public ParserEventForward getParserEventForward(@NonNull final Source source) {
906
            return source.peFwd;
907
        }
809
    } // End of MySourceAccessor class
908
    } // End of MySourceAccessor class
810
        
909
        
811
    static class ASourceModificationEvent extends SourceModificationEvent {
910
    private static class ASourceModificationEvent extends SourceModificationEvent {
812
911
813
        private int         startOffset;
912
        private int         startOffset;
814
        private int         endOffset;
913
        private int         endOffset;
Lines 829-835 Link Here
829
            int             _endOffset
928
            int             _endOffset
830
        ) {
929
        ) {
831
            startOffset = Math.min (startOffset, _startOffset);
930
            startOffset = Math.min (startOffset, _startOffset);
832
            endOffset = Math.min (endOffset, _endOffset);
931
            endOffset = Math.max (endOffset, _endOffset);
932
        }
933
934
        @Override
935
        public int getAffectedStartOffset() {
936
            return startOffset;
937
        }
938
939
        @Override
940
        public int getAffectedEndOffset() {
941
            return endOffset;
833
        }
942
        }
834
943
835
        @Override
944
        @Override
Lines 838-841 Link Here
838
            return "SourceModificationEvent " + startOffset + ":" + endOffset;
947
            return "SourceModificationEvent " + startOffset + ":" + endOffset;
839
        }
948
        }
840
    }
949
    }
950
951
    /**
952
     * Returns a Lookup providing a context for the source.
953
     * In the presence of multiple scopes or users in the system, this Lookup may
954
     * provide access to necessary context-dependent services or scope-dependent data.
955
     * <p/>
956
     * A Source may be created with a Lookup, or it will use the default Lookup as a context
957
     * @return Lookup.
958
     * @since 9.2
959
     */
960
    public Lookup getLookup() {
961
        return context;
962
    }
841
}
963
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/impl/IndexerBridge.java (+67 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.parsing.impl;
44
45
/**
46
 * This interface is a pseudoAPI between Parsing and Indexing support.
47
 * The Parsing support needs to communicate with Indexing and coordinate task planning.
48
 * Indexing API can use impl dependency on Parsing API to call the necessary services,
49
 * but Parsing API must use a bridge implemented by Indexing to call back.
50
 * <p/>
51
 * This pseudoAPI can be changed at any time without any warning! 
52
 * 
53
 * @author sdedic
54
 * @since 9.2
55
 */
56
public interface IndexerBridge {
57
    /**
58
     * @return True if the indexer is in any other state than idle.
59
     */
60
    public boolean isIndexing();
61
    
62
    /**
63
     * 
64
     * @return true, if the calling thread executes in the indexer's protected mode.
65
     */
66
    public boolean ownsProtectedMode();
67
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/EnvironmentFactory.java (+113 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.parsing.implspi;
44
45
import java.util.Collection;
46
import java.util.concurrent.Callable;
47
import org.netbeans.api.annotations.common.CheckForNull;
48
import org.netbeans.api.annotations.common.NonNull;
49
import org.netbeans.api.annotations.common.NullAllowed;
50
import org.netbeans.modules.parsing.api.Source;
51
import org.netbeans.modules.parsing.spi.Parser;
52
import org.netbeans.modules.parsing.spi.Scheduler;
53
import org.openide.util.Lookup;
54
55
/**
56
 * Factory for {@link SourceEnvironment} instances. The Factory method is given
57
 * a {@link Source.EnvControl} object so the created SourceEnvironment may
58
 * manipulate the Source state using privileged APIs.
59
 * <p/>
60
 * An instance of this Provider must be registered in the default Lookup. The first
61
 * instance found will be used.
62
 * @since 9.2
63
 */
64
public interface EnvironmentFactory {
65
    /**
66
     * Provides access to context-dependent Lookup, to multi-user environment
67
     * @return context-depedent Lookup
68
     */
69
    public Lookup   getContextLookup();
70
    
71
    /**
72
     * Parovides a class of a predefined Scheduler.
73
     * The predefined Schedulers are available as final field values.
74
     *
75
     * @param schedulerName
76
     * @return
77
     */
78
    @CheckForNull
79
    public Class<? extends Scheduler> findStandardScheduler(@NonNull String schedulerName);
80
    
81
    /**
82
     * Creates parser for the mime type
83
     * @param mimeType
84
     * @return 
85
     */
86
    public Parser   findMimeParser(Lookup context, String mimeType);
87
    
88
    public Collection<? extends Scheduler> getSchedulers(Lookup context);
89
90
    /**
91
     * Creates an environment for the specified Source.
92
     * The passed control object may be {@code null}, which means the source cannot
93
     * be controlled by environment and listening may not be necessary.
94
     *
95
     * @param src the Source instance
96
     * @param control the control object; if null, the source cannot be controlled.
97
     * @return the SourceEnvironment, must not be null.
98
     */
99
    @NonNull
100
    public SourceEnvironment createEnvironment(@NonNull Source src, @NullAllowed SourceControl control);
101
    
102
    
103
    /**
104
     * Runs a priority I/O operation. The environment may lock out or suspend 
105
     * some (background) activities during the priority I/O operation.
106
     * 
107
     * @param <T> type of result
108
     * @param r the code to execute
109
     * @return computed result
110
     * @throws Exception propagated from the executed code
111
     */
112
    public abstract <T> T runPriorityIO (final Callable<T> r) throws Exception;
113
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/ProfilerSupport.java (+76 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
*/
42
43
package org.netbeans.modules.parsing.implspi;
44
45
import java.io.DataOutputStream;
46
import java.io.IOException;
47
48
/**
49
 * Semi-private SPI for self-profiling of the parsing system.
50
 *
51
 * @author sdedic
52
 * @since 9.2
53
 */
54
public abstract class ProfilerSupport {
55
    /**
56
     * Starts the profiling. The support will collect data until {@link #cancel} or {@link #stopAndSnapshot}
57
     * is called.
58
     */
59
    public abstract void start();
60
    
61
    /**
62
     * Cancels the profiling and discards data already collected.
63
     */
64
    public abstract void cancel();
65
    
66
    /**
67
     * Stops the profiling and flushes the data.
68
     * 
69
     * @param dos output stream to store the collected data.
70
     */
71
    public abstract void stopAndSnapshot(DataOutputStream dos) throws IOException;
72
    
73
    public interface Factory {
74
        public ProfilerSupport  create(String id);
75
    }
76
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/SchedulerControl.java (+69 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.parsing.implspi;
44
45
import org.netbeans.modules.parsing.api.Source;
46
import org.netbeans.modules.parsing.spi.Scheduler;
47
48
/**
49
 * Allows the environment implementation to reschedule tasks for a
50
 * source. The instance is passed to {@link SourceEnvironment#attachScheduler}.
51
 * @author sdedic
52
 * @since 9.2
53
 */
54
public interface SchedulerControl {
55
    /**
56
     * Provides access to the controlled Scheduler
57
     * @return the scheduler instance
58
     */
59
    public Scheduler getScheduler();
60
    
61
    /**
62
     * Notifies about Source change. Should be called when the scheduler
63
     * should reschedule source's tasks or when the Source itself changes, i.e.
64
     * file is moved/renamed etc.
65
     * 
66
     * @param newSource the current Source for the Scheduler
67
     */
68
    public void sourceChanged(Source newSource);
69
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/SourceControl.java (+172 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.parsing.implspi;
44
45
import java.util.EnumSet;
46
import java.util.Set;
47
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.modules.parsing.api.Source;
49
import org.netbeans.modules.parsing.impl.SourceAccessor;
50
import org.netbeans.modules.parsing.impl.SourceFlags;
51
import org.netbeans.modules.parsing.impl.TaskProcessor;
52
import org.openide.util.Parameters;
53
import org.openide.util.RequestProcessor;
54
55
/**
56
 * Allows to control Source state within the Parsing subsystem based on
57
 * external events.
58
 * The {@link SourceEnvironment} gets this instance to forward interesting
59
 * events to the parser. It is possible to invalidate the source, region of source.
60
 * @author sdedic
61
 * @since 9.2
62
 */
63
public final class SourceControl {
64
65
    private static final RequestProcessor RP = new RequestProcessor (
66
        "parsing-event-collector",         //NOI18N
67
        1,
68
        false,
69
        false);
70
71
    private final RequestProcessor.Task resetTask;
72
73
    private final Source source;
74
75
    /**
76
     * Creates a new control object for the source.
77
     * 
78
     * @param source the source which is controlled
79
     */
80
    public SourceControl(@NonNull final Source source) {
81
        Parameters.notNull("source", source);   //NOI18N
82
        this.source = source;
83
        this.resetTask = RP.create(new Runnable() {
84
            @Override
85
            public void run() {
86
                if (SourceAccessor.getINSTANCE().getEnv(source).isReparseBlocked()) {
87
                    return;
88
                }
89
                TaskProcessor.resetStateImpl(source);
90
            }
91
        });
92
    }
93
94
95
    /**
96
     * Provides reference to the Source. The reference is provided for convenience
97
     * to help proper garbage collection of the Source object. If the client keeps
98
     * a Source instance, it should use WeakReference to store it.
99
     * @return Source instance or {@code null}
100
     */
101
    @NonNull
102
    public Source getSource() {
103
        return source;
104
    }
105
106
    /**
107
     * Informs that the source was changed in an unspecified way, and possibly
108
     * its mime was changed.
109
     * The source will be reparsed and if {@code mimeChanged} is true, the MIME
110
     * type will be re-read and the appropriate parser will be used for parsing.
111
     * <p/>
112
     * The {@code mimeChanged} flag is used for optimization; set it aggressively,
113
     * so proper parser is looked up.
114
     * 
115
     * @param mimeChanged true, if mime type might have changed.
116
     */
117
    public void sourceChanged(final boolean mimeChanged) {
118
        final SourceAccessor sa = SourceAccessor.getINSTANCE();
119
        final Set<SourceFlags> flags = EnumSet.of(
120
            SourceFlags.CHANGE_EXPECTED,
121
            SourceFlags.INVALID,
122
            SourceFlags.RESCHEDULE_FINISHED_TASKS);
123
        if (mimeChanged) {
124
            sa.mimeTypeMayChanged(source);
125
        }
126
        sa.setSourceModification(source, true, -1, -1);
127
        sa.setFlags(source, flags);
128
        TaskProcessor.resetState(source, true, true);
129
    }
130
131
    /**
132
     * Informs that part of the source was edited. The parser implementation
133
     * may reparse just a portion of the text or a whole (depends on the 
134
     * implementation). Setting {@code startOffset} or {@code endOffset}
135
     * to -1 will execute an equivalent of {@code sourceChanged(false)}.
136
     * 
137
     * @param startOffset start of the change
138
     * @param endOffset end of the change
139
     */
140
    public void regionChanged(int startOffset, int endOffset) {
141
        final SourceAccessor sa = SourceAccessor.getINSTANCE();
142
        final Set<SourceFlags> flags = EnumSet.of(
143
            SourceFlags.CHANGE_EXPECTED,
144
            SourceFlags.INVALID,
145
            SourceFlags.RESCHEDULE_FINISHED_TASKS);
146
        sa.setSourceModification(source, true, startOffset, endOffset);
147
        sa.setFlags(source, flags);
148
        TaskProcessor.resetState(source, true, true);
149
    }
150
151
    /**
152
     * Informs about a non-text change in the Source, such as caret movement
153
     * or focus. Does not invalidate the parsing result, but may re-execute certain
154
     * tasks.
155
     */
156
    public void stateChanged() {
157
        final SourceAccessor sa = SourceAccessor.getINSTANCE();
158
        final Set<SourceFlags> flags = EnumSet.of(SourceFlags.CHANGE_EXPECTED);
159
        sa.setSourceModification(source, false, -1, -1);
160
        sa.setFlags(source, flags);
161
        TaskProcessor.resetState(source, false, true);
162
    }
163
164
    /**
165
     * Marks the source for reparsing after the specified delay.
166
     *
167
     * @param delay time in milliseconds.
168
     */
169
    public void revalidate(int delay) {
170
        resetTask.schedule(delay);
171
    }
172
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/SourceEnvironment.java (+166 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.parsing.implspi;
43
44
import java.io.IOException;
45
import javax.swing.event.ChangeListener;
46
import javax.swing.text.Document;
47
import org.netbeans.api.annotations.common.CheckForNull;
48
import org.netbeans.api.annotations.common.NonNull;
49
import org.netbeans.modules.parsing.api.Source;
50
import org.netbeans.modules.parsing.impl.ParserEventForward;
51
import org.netbeans.modules.parsing.impl.SourceAccessor;
52
import org.netbeans.modules.parsing.impl.event.FileChangeSupport;
53
import org.netbeans.modules.parsing.impl.event.ParserChangeSupport;
54
import org.openide.filesystems.FileChangeListener;
55
import org.openide.filesystems.FileObject;
56
import org.openide.filesystems.FileUtil;
57
import org.openide.util.Parameters;
58
59
/**
60
 * Connects the Source instance to its environment.It is not implemented by
61
 * Parsing API as it may introduce extra dependencies on file or object access
62
 * libraries (e.g. Data Systems API). In exchange, the Provider gets a control
63
 * interface, which can be used to signal source change events originating from
64
 * the storage/file/DataObject.
65
 * <p/>
66
 * Instance of the SourceEnvironment is referenced from the Source object. It is 
67
 * advised not to store Source reference, but rather extract the Source instance
68
 * from the {@link Source.EnvControl} to allow Source instances to be GCed. 
69
 * 
70
 * @author sdedic
71
 * @since 9.2
72
 */
73
public abstract class SourceEnvironment {
74
75
    private final SourceControl sourceControl;
76
    private FileChangeListener fileChangeListener;
77
    private ChangeListener parserListener;
78
79
    /**
80
     * Initialized a new SourceEnvironment.
81
     * @param sourceControl handle to control a Source object
82
     */
83
    protected SourceEnvironment(@NonNull final SourceControl sourceControl) {
84
        Parameters.notNull("sourceControl", sourceControl); //NOI18N
85
        this.sourceControl = sourceControl;
86
    }
87
    /**
88
     * Reads the Document based on the Source's properties
89
     *
90
     * @param f the FIleObject
91
     * @param forceOpen true, if the document should be opened even though
92
     * it does not exist yet
93
     * @return the document, or {@code null} if the document was not opened.
94
     */
95
    @CheckForNull
96
    public abstract Document readDocument(@NonNull FileObject f, boolean forceOpen) throws IOException;
97
    
98
    /**
99
     * Attaches a Scheduler to the source in this environment. The implementation
100
     * may need to listen on certain environment objects in order to schedule
101
     * tasks at appropriate time.
102
     * <p/>
103
     * 
104
     * @param s the scheduler to attach or detach
105
     * @param attach if false, the scheduler is just detached from the source.
106
     */
107
    public abstract void attachScheduler(@NonNull SchedulerControl s, boolean attach);
108
109
    /**
110
     * Notifies that the source was actually used, and the parser wants to be
111
     * notified on changes through {@link SourceControl}.
112
     * Until this method is called, the environment implementation need not to
113
     * listen or forward source affecting events to the parser API.
114
     */
115
    public abstract void activate();
116
117
    /**
118
     * Returns true, if reparse should NOT occur immediately when source is invalidated.
119
     * This is used when e.g. completion is active; postpones reparsing. The SourceEnvironment
120
     * is responsible for calling {@link SourceControl#revalidate()} when the condition changes.
121
     * 
122
     * @return true, if a reparse should not be scheduled.
123
     */
124
    public abstract boolean isReparseBlocked();
125
126
    /**
127
     * Returns the {@link SourceControl}.
128
     * @return the {@link SourceControl}
129
     */
130
    protected final SourceControl getSourceControl() {
131
        return this.sourceControl;
132
    }
133
134
    /**
135
     * Starts listening on file changes.
136
     * Should be called from {@link SourceEnvironment#activate}
137
     */
138
    protected final void listenOnFileChanges() {
139
        final FileObject fo = sourceControl.getSource().getFileObject();
140
        if (fo != null) {
141
            fileChangeListener = new FileChangeSupport(sourceControl);
142
            fo.addFileChangeListener(FileUtil.weakFileChangeListener(this.fileChangeListener,fo));
143
        }
144
    }
145
146
    /**
147
     * Starts listening on {@link Source} parsers.
148
     * Should be called from {@link SourceEnvironment#activate}
149
     */
150
    protected final void listenOnParser() {
151
        final ParserEventForward peFwd = SourceAccessor.getINSTANCE().getParserEventForward(
152
            sourceControl.getSource());
153
        parserListener = new ParserChangeSupport(sourceControl);
154
        peFwd.addChangeListener(parserListener);
155
    }
156
157
    /**
158
     * Returns a {@link SourceEnvironment} for given {@link Source}.
159
     * @param source the {@link Source} to return {@link SourceEnvironment} for
160
     * @return the {@link SourceEnvironment}
161
     */
162
    @NonNull
163
    protected static SourceEnvironment forSource(@NonNull final Source source) {
164
        return SourceAccessor.getINSTANCE().getEnv(source);
165
    }
166
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/TaskProcessorControl.java (+83 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
  */
42
43
package org.netbeans.modules.parsing.implspi;
44
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.modules.parsing.api.Source;
47
import org.netbeans.modules.parsing.impl.SourceAccessor;
48
import org.netbeans.modules.parsing.impl.TaskProcessor;
49
import org.openide.util.Parameters;
50
51
/**
52
 * Allows to control the parsing susbsytem operation.
53
 * @author sdedic
54
 * @since 9.2
55
 */
56
public final class TaskProcessorControl {
57
    /**
58
     * Initialize the parsing and scheduling system. The method should be called 
59
     * at "appropriate time", for example when the UI starts and is ready to accept
60
     * user input.
61
     */
62
    public static void initialize() {
63
        SourceAccessor.getINSTANCE().init();
64
    }
65
66
    /**
67
     * Suspends {@link SchedulerTask}s execution.
68
     * Cancels currently running {@link SchedulerTask} and do
69
     * not schedule any ready {@link SchedulerTask}.
70
     */
71
    public static void suspendSchedulerTasks(@NonNull final Source source) {
72
        Parameters.notNull("source", source);   //NOI18N
73
        TaskProcessor.resetState(source, true, true);
74
    }
75
76
    /**
77
     * Resumes {@link SchedulerTask}s execution.
78
     * Schedules ready {@link SchedulerTask}s.
79
     */
80
    public static void resumeSchedulerTasks() {
81
        TaskProcessor.resetStateImpl(null);
82
    }
83
}
(-)a/parsing.api/src/org/netbeans/modules/parsing/implspi/package.html (+49 lines)
Line 0 Link Here
1
<!DOCTYPE html>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 2014 Oracle and/or its affiliates. All rights reserved.
6
7
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
8
Other names may be trademarks of their respective owners.
9
10
The contents of this file are subject to the terms of either the GNU
11
General Public License Version 2 only ("GPL") or the Common
12
Development and Distribution License("CDDL") (collectively, the
13
"License"). You may not use this file except in compliance with the
14
License. You can obtain a copy of the License at
15
http://www.netbeans.org/cddl-gplv2.html
16
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
17
specific language governing permissions and limitations under the
18
License.  When distributing the software, include this License Header
19
Notice in each file and include the License file at
20
nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
21
particular file as subject to the "Classpath" exception as provided
22
by Oracle in the GPL Version 2 section of the License file that
23
accompanied this code. If applicable, add the following below the
24
License Header, with the fields enclosed by brackets [] replaced by
25
your own identifying information:
26
"Portions Copyrighted [year] [name of copyright owner]"
27
28
If you wish your version of this file to be governed by only the CDDL
29
or only the GPL Version 2, indicate your decision by adding
30
"[Contributor] elects to include this software in this distribution
31
under the [CDDL or GPL Version 2] license." If you do not indicate a
32
single choice of license, a recipient has the option to distribute
33
your version of this file under either the CDDL, the GPL Version 2 or
34
to extend the choice of license to its licensees as provided above.
35
However, if you add GPL Version 2 code and therefore, elected the GPL
36
Version 2 license, then the option applies only if the new code is
37
made subject to such option by the copyright holder.
38
39
Contributor(s):
40
41
Portions Copyrighted 2014 Sun Microsystems, Inc.
42
-->
43
<html>
44
    <body>
45
        This package contains SPI and callbacks to bind Parser support to the environment
46
        - FileObjects, DataObjects or windowing system. Only a single implementation of
47
        the EnvironmentFactory is expected.
48
    </body>
49
</html>
(-)a/parsing.api/src/org/netbeans/modules/parsing/spi/EmbeddingProvider.java (-2 / +1 lines)
Lines 49-55 Link Here
49
import java.util.List;
49
import java.util.List;
50
import org.netbeans.modules.parsing.api.Embedding;
50
import org.netbeans.modules.parsing.api.Embedding;
51
import org.netbeans.modules.parsing.api.Snapshot;
51
import org.netbeans.modules.parsing.api.Snapshot;
52
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
53
52
54
53
55
/**
54
/**
Lines 93-99 Link Here
93
     * Registration of the {@link EmbeddingProvider}.
92
     * Registration of the {@link EmbeddingProvider}.
94
     * Creates a mime lookup registration of the {@link TaskFactory} for
93
     * Creates a mime lookup registration of the {@link TaskFactory} for
95
     * annotated {@link EmbeddingProvider}. It also provides the target
94
     * annotated {@link EmbeddingProvider}. It also provides the target
96
     * mime type of the created embedding which allows the {@link QuerySupport}
95
     * mime type of the created embedding which allows the indexing QuerySupport
97
     * to correctly mark dirty embedded indexers.
96
     * to correctly mark dirty embedded indexers.
98
     *
97
     *
99
     * @since 1.57
98
     * @since 1.57
(-)a/parsing.api/src/org/netbeans/modules/parsing/spi/Scheduler.java (-59 / +51 lines)
Lines 42-66 Link Here
42
42
43
package org.netbeans.modules.parsing.spi;
43
package org.netbeans.modules.parsing.spi;
44
44
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
45
import java.beans.PropertyChangeListener;
47
import java.util.logging.Level;
48
import java.util.logging.Logger;
46
import java.util.logging.Logger;
49
import org.netbeans.api.annotations.common.CheckForNull;
47
import org.netbeans.api.annotations.common.CheckForNull;
50
import org.netbeans.modules.parsing.api.Source;
48
import org.netbeans.modules.parsing.api.Source;
51
import org.netbeans.modules.parsing.impl.CurrentDocumentScheduler;
52
import org.netbeans.modules.parsing.impl.CursorSensitiveScheduler;
53
import org.netbeans.modules.parsing.impl.SchedulerAccessor;
49
import org.netbeans.modules.parsing.impl.SchedulerAccessor;
54
import org.netbeans.modules.parsing.impl.SelectedNodesScheduler;
55
import org.netbeans.modules.parsing.impl.SourceAccessor;
50
import org.netbeans.modules.parsing.impl.SourceAccessor;
56
import org.netbeans.modules.parsing.impl.SourceCache;
51
import org.netbeans.modules.parsing.impl.SourceCache;
57
import org.openide.filesystems.FileObject;
52
import org.netbeans.modules.parsing.impl.Utilities;
58
import org.openide.loaders.DataObject;
53
import org.netbeans.modules.parsing.implspi.SchedulerControl;
59
import org.openide.loaders.DataObjectNotFoundException;
60
61
import org.openide.util.RequestProcessor;
54
import org.openide.util.RequestProcessor;
62
import org.openide.util.RequestProcessor.Task;
55
import org.openide.util.RequestProcessor.Task;
63
import org.openide.util.WeakListeners;
64
56
65
57
66
/**
58
/**
Lines 85-107 Link Here
85
77
86
    private static final Logger LOG = Logger.getLogger(Scheduler.class.getName());
78
    private static final Logger LOG = Logger.getLogger(Scheduler.class.getName());
87
79
88
    private final PropertyChangeListener listener = new PropertyChangeListener() {
89
        @Override
90
        public void propertyChange(PropertyChangeEvent evt) {
91
            if (DataObject.PROP_PRIMARY_FILE.equals(evt.getPropertyName())) {
92
                final DataObject dobj = (DataObject) evt.getSource();
93
                final Source newSource = Source.create(dobj.getPrimaryFile());
94
                if (newSource != null) {
95
                    LOG.log(
96
                        Level.FINE,
97
                        "Rescheduling {0} due to change of primary file.",  //NOI18N
98
                        dobj.getPrimaryFile());
99
                    schedule(newSource, new SchedulerEvent(newSource));
100
                }
101
            }
102
        }
103
    };
104
    
105
    /**
80
    /**
106
     * May be changed by unit test
81
     * May be changed by unit test
107
     */
82
     */
Lines 121-127 Link Here
121
     * </ol>
96
     * </ol>
122
     */
97
     */
123
    public static final Class<? extends Scheduler>
98
    public static final Class<? extends Scheduler>
124
                            CURSOR_SENSITIVE_TASK_SCHEDULER = CursorSensitiveScheduler.class;
99
                            CURSOR_SENSITIVE_TASK_SCHEDULER;
125
    
100
    
126
    /**
101
    /**
127
     * This implementations of {@link Scheduler} reschedules all tasks when:
102
     * This implementations of {@link Scheduler} reschedules all tasks when:
Lines 131-145 Link Here
131
     * </ol>
106
     * </ol>
132
     */
107
     */
133
    public static final Class<? extends Scheduler>
108
    public static final Class<? extends Scheduler>
134
                            EDITOR_SENSITIVE_TASK_SCHEDULER = CurrentDocumentScheduler.class;
109
                            EDITOR_SENSITIVE_TASK_SCHEDULER;
135
    
110
    
136
    /**
111
    /**
137
     * This implementations of {@link Scheduler} reschedules all tasks when
112
     * This implementations of {@link Scheduler} reschedules all tasks when
138
     * nodes selected in editor are changed.
113
     * nodes selected in editor are changed.
139
     */
114
     */
140
    public static final Class<? extends Scheduler>
115
    public static final Class<? extends Scheduler>
141
                            SELECTED_NODES_SENSITIVE_TASK_SCHEDULER = SelectedNodesScheduler.class;
116
                            SELECTED_NODES_SENSITIVE_TASK_SCHEDULER;
142
117
118
    static {
119
        CURSOR_SENSITIVE_TASK_SCHEDULER = Utilities.findDefaultScheduler("CURSOR_SENSITIVE_TASK_SCHEDULER");
120
        EDITOR_SENSITIVE_TASK_SCHEDULER = Utilities.findDefaultScheduler("EDITOR_SENSITIVE_TASK_SCHEDULER");
121
        SELECTED_NODES_SENSITIVE_TASK_SCHEDULER = Utilities.findDefaultScheduler("SELECTED_NODES_SENSITIVE_TASK_SCHEDULER");
122
    }
123
    
143
    /**
124
    /**
144
     * Reschedule all tasks registered for <code>this</code> Scheduler (see
125
     * Reschedule all tasks registered for <code>this</code> Scheduler (see
145
     * {@link ParserResultTask#getSchedulerClass()}.
126
     * {@link ParserResultTask#getSchedulerClass()}.
Lines 155-160 Link Here
155
                            requestProcessor;
136
                            requestProcessor;
156
    private Task            task;
137
    private Task            task;
157
    
138
    
139
    private final SchedulerControl         ctrl = new Control(this);
140
    
158
    /**
141
    /**
159
     * Reschedule all tasks registered for <code>this</code> Scheduler (see
142
     * Reschedule all tasks registered for <code>this</code> Scheduler (see
160
     * {@link ParserResultTask#getSchedulerClass()}, and sets new {@link Source}s for them.
143
     * {@link ParserResultTask#getSchedulerClass()}, and sets new {@link Source}s for them.
Lines 177-221 Link Here
177
                    false,
160
                    false,
178
                    false);
161
                    false);
179
        }        
162
        }        
180
        if (this.source != source) {
163
        boolean different = this.source != source;
164
        
165
        if (different) {
181
            if (this.source != null) {
166
            if (this.source != null) {
182
                final SourceCache cache = SourceAccessor.getINSTANCE().getCache(this.source);
167
                final SourceCache cache = SourceAccessor.getINSTANCE().getCache(this.source);
183
                cache.unscheduleTasks(Scheduler.this.getClass());
168
                cache.unscheduleTasks(Scheduler.this.getClass());
184
                if (wlistener != null) {
169
                SourceAccessor.getINSTANCE().attachScheduler(this.source, ctrl, false);
185
                    final FileObject fo = this.source.getFileObject();
186
                    if (fo != null) {
187
                        try {
188
                            final DataObject dobj = DataObject.find(fo);
189
                            dobj.removePropertyChangeListener(wlistener);
190
                        } catch (DataObjectNotFoundException nfe) {
191
                            //No DataObject for file - ignore
192
                        }
193
                    }
194
                }
195
            }
170
            }
196
            this.source = source;
171
            this.source = source;
197
            if (source != null) {
198
                final FileObject fo = source.getFileObject();
199
                if (fo != null) {
200
                    try {
201
                        final DataObject dobj = DataObject.find(fo);
202
                        wlistener = WeakListeners.propertyChange(listener, dobj);
203
                        dobj.addPropertyChangeListener(wlistener);
204
                    } catch (DataObjectNotFoundException ex) {
205
                        //No DataObject for file - ignore
206
                    }
207
                }
208
            }
209
        }
172
        }
210
        if (source == null) {
173
        if (source == null) {
211
            return;
174
            return;
212
        }
175
        }
176
        if (different) {
177
            SourceAccessor.getINSTANCE().attachScheduler(source, ctrl, true);
178
        }
213
        task = requestProcessor.create (new Runnable () {
179
        task = requestProcessor.create (new Runnable () {
214
            @Override
180
            @Override
215
            public void run () {
181
            public void run () {
216
                SourceCache cache = SourceAccessor.getINSTANCE ().getCache (source);                
182
                SourceCache cache = SourceAccessor.getINSTANCE ().getCache (source);                
217
                SourceAccessor.getINSTANCE ().setSchedulerEvent (source, Scheduler.this, event);
183
                SourceAccessor.getINSTANCE ().setSchedulerEvent (source, Scheduler.this, event);
218
                //S ystem.out.println ("\nSchedule tasks (" + Scheduler.this + "):");
184
                //S ystem.out.println ("\nSchedule tasks (" + Scheduler.this + "):");
185
                LOG.fine("Scheduling tasks for :" + source + " and scheduler " + this);
219
                cache.scheduleTasks (Scheduler.this.getClass ());
186
                cache.scheduleTasks (Scheduler.this.getClass ());
220
            }
187
            }
221
        });
188
        });
Lines 247-256 Link Here
247
            return scheduler.createSchedulerEvent (event);
214
            return scheduler.createSchedulerEvent (event);
248
        }
215
        }
249
    }
216
    }
217
    
218
    /**
219
     * Allows to control the scheduler and schedule tasks. An instance of Control
220
     * is passed to the {@link SourceEnvironment#attachScheduler} method when the
221
     * Source is bound to a Scheduler.
222
     * <p/>
223
     * The client is NOT expected to create instances of this class;
224
     */
225
    private static final class Control implements SchedulerControl {
226
        private final Scheduler scheduler;
227
228
        /**
229
         *
230
         * @param scheduler
231
         */
232
        public Control(final Scheduler scheduler) {
233
            super();
234
            this.scheduler = scheduler;
235
        }
236
237
        public Scheduler getScheduler() {
238
            return scheduler;
239
        }
240
241
        @Override
242
        public void sourceChanged(Source newSource) {
243
            scheduler.schedule(newSource, new SchedulerEvent(newSource));
244
        }
245
    }
246
    
250
}
247
}
251
248
252
253
254
255
256
(-)a/parsing.api/src/org/netbeans/modules/parsing/spi/SourceModificationEvent.java (-1 / +18 lines)
Lines 52-58 Link Here
52
public class SourceModificationEvent extends EventObject {
52
public class SourceModificationEvent extends EventObject {
53
    
53
    
54
    private final boolean sourceChanged;
54
    private final boolean sourceChanged;
55
56
    
55
    
57
    /**
56
    /**
58
     * Creates a new {@link SourceModificationEvent}
57
     * Creates a new {@link SourceModificationEvent}
Lines 92-103 Link Here
92
    public boolean sourceChanged() {
91
    public boolean sourceChanged() {
93
        return sourceChanged;
92
        return sourceChanged;
94
    }
93
    }
94
    
95
    /**
96
     * Returns start offset of the change that affected the source.
97
     * @return offset or -1 if the source was not affected
98
     * @since 9.1
99
     */
100
    public int getAffectedStartOffset() {
101
        return -1;
102
    }
95
103
104
    /**
105
     * Returns end offset of the change that affected the source.
106
     * @return offset or -1 if the source was not affected
107
     * @since 9.1
108
     */
109
    public int getAffectedEndOffset() {
110
        return -1;
111
    }
112
    
96
    @Override
113
    @Override
97
    public String toString () {
114
    public String toString () {
98
        return "SourceModificationEvent " + hashCode () + "(source: " + source + ")";
115
        return "SourceModificationEvent " + hashCode () + "(source: " + source + ")";
99
    }
116
    }
100
}
117
}

Return to bug 247161