diff --git a/html.editor/src/org/netbeans/modules/html/editor/gsf/embedding/CssEmbeddingProvider.java b/html.editor/src/org/netbeans/modules/html/editor/gsf/embedding/CssEmbeddingProvider.java --- a/html.editor/src/org/netbeans/modules/html/editor/gsf/embedding/CssEmbeddingProvider.java +++ b/html.editor/src/org/netbeans/modules/html/editor/gsf/embedding/CssEmbeddingProvider.java @@ -47,46 +47,27 @@ import org.netbeans.modules.parsing.api.Embedding; import org.netbeans.modules.parsing.api.Snapshot; import org.netbeans.modules.parsing.spi.EmbeddingProvider; -import org.netbeans.modules.parsing.spi.SchedulerTask; -import org.netbeans.modules.parsing.spi.TaskFactory; /** * * @author marekfukala */ +@EmbeddingProvider.Registration( + mimeType="text/html", + targetMimeType="text/css" +) public class CssEmbeddingProvider extends EmbeddingProvider { private static final Logger LOG = Logger.getLogger(CssEmbeddingProvider.class.getSimpleName()); - private static final long MAX_SNAPSHOT_SIZE = 4 * 1024 * 1024; //4MB - - public static class Factory extends TaskFactory { + private static final String HTML_MIME_TYPE = "text/html"; // NOI18N - private static final String HTML_MIME_TYPE = "text/html"; // NOI18N + private String sourceMimeType; + private Translator translator; - private static final Map translators = new HashMap(); - - static { - translators.put(HTML_MIME_TYPE, new CssHtmlTranslator()); //xxx can I use shared instance??? - } - - @Override - public Collection create(Snapshot snapshot) { - - int slen = snapshot.getText().length(); - LOG.fine(String.format("CssEmbeddingProvider.create(snapshot): mimetype: %s, size: %s", snapshot.getMimeType(), slen)); //NOI18N - if(slen > MAX_SNAPSHOT_SIZE) { - LOG.fine(String.format("Size %s > maximum (%s) => providing no css embedding", slen, MAX_SNAPSHOT_SIZE)); //NOI18N - return Collections.emptyList(); - } - - Translator t = translators.get(snapshot.getMimeType()); - if (t != null) { - return Collections.singleton(new CssEmbeddingProvider(snapshot.getMimeType(), t)); - } else { - return Collections.emptyList(); - } - } + public CssEmbeddingProvider() { + this.sourceMimeType = HTML_MIME_TYPE; + this.translator = new CssHtmlTranslator(); } public static interface Translator { @@ -95,18 +76,15 @@ } - - private String sourceMimeType; - private Translator translator; - - private CssEmbeddingProvider(String sourceMimeType, Translator translator) { - this.sourceMimeType = sourceMimeType; - this.translator = translator; - } - @Override public List getEmbeddings(Snapshot snapshot) { if (sourceMimeType.equals(snapshot.getMimeType())) { + int slen = snapshot.getText().length(); + LOG.fine(String.format("CssEmbeddingProvider.create(snapshot): mimetype: %s, size: %s", snapshot.getMimeType(), slen)); //NOI18N + if(slen > MAX_SNAPSHOT_SIZE) { + LOG.fine(String.format("Size %s > maximum (%s) => providing no css embedding", slen, MAX_SNAPSHOT_SIZE)); //NOI18N + return Collections.emptyList(); + } List embeddings = translator.getEmbeddings(snapshot); if(embeddings.isEmpty()) { return Collections.emptyList(); diff --git a/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml b/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml --- a/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml +++ b/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml @@ -85,10 +85,7 @@ - - - - + diff --git a/parsing.api/apichanges.xml b/parsing.api/apichanges.xml --- a/parsing.api/apichanges.xml +++ b/parsing.api/apichanges.xml @@ -110,6 +110,23 @@ + + + Added EmbeddingProvider.Registration annotation to register EmbeddingProviders. + + + + + +

+ Added EmbeddingProvider.Registration annotation to register EmbeddingProviders. + The registration provides a mime type of a generated embedding which allows the infrastructure to correctly + handle embedded indexes. +

+
+ + +
Added SuspendStatus service which can be used by indexers to find out if diff --git a/parsing.api/nbproject/project.properties b/parsing.api/nbproject/project.properties --- a/parsing.api/nbproject/project.properties +++ b/parsing.api/nbproject/project.properties @@ -3,7 +3,7 @@ javac.source=1.6 javadoc.apichanges=${basedir}/apichanges.xml javadoc.arch=${basedir}/arch.xml -spec.version.base=1.56.0 +spec.version.base=1.57.0 test.config.stableBTD.includes=**/*Test.class test.config.stableBTD.excludes=\ diff --git a/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderFactory.java b/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderFactory.java new file mode 100644 --- /dev/null +++ b/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderFactory.java @@ -0,0 +1,94 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.parsing.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.modules.parsing.api.Snapshot; +import org.netbeans.modules.parsing.spi.EmbeddingProvider; +import org.netbeans.modules.parsing.spi.SchedulerTask; +import org.netbeans.modules.parsing.spi.TaskFactory; +import org.openide.util.Parameters; + +/** + * + * @author Tomas Zezula + */ +public class EmbeddingProviderFactory extends TaskFactory { + + public static final String ATTR_TARGET_MIME_TYPE = "targetMimeType"; //NOI18N + public static final String ATTR_PROVIDER = "provider"; //NOI18N + + private final Map params; + private final String targetMimeType; + + private EmbeddingProviderFactory(@NonNull final Map params) { + Parameters.notNull("definition", params); //NOI18N + this.params = params; + this.targetMimeType = (String) params.get(ATTR_TARGET_MIME_TYPE); + if (this.targetMimeType == null) { + throw new IllegalArgumentException( + String.format( + "The definition file has no %s attribute.", //NOI18N + ATTR_TARGET_MIME_TYPE)); + } + } + + public String getTargetMimeType() { + return this.targetMimeType; + } + + @NonNull + @Override + public Collection create (@NonNull final Snapshot snapshot) { + final Object delegate = params.get(ATTR_PROVIDER); + return (delegate instanceof EmbeddingProvider) ? + Collections.singleton((EmbeddingProvider)delegate) : + Collections.emptySet(); + } + + public static TaskFactory create(@NonNull final Map params) { + return new EmbeddingProviderFactory(params); + } +} diff --git a/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderRegistrationProcessor.java b/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderRegistrationProcessor.java new file mode 100644 --- /dev/null +++ b/parsing.api/src/org/netbeans/modules/parsing/impl/EmbeddingProviderRegistrationProcessor.java @@ -0,0 +1,99 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.parsing.impl; + +import java.util.Collections; +import java.util.Set; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import org.netbeans.modules.parsing.spi.EmbeddingProvider; +import org.netbeans.modules.parsing.spi.TaskFactory; +import org.openide.filesystems.annotations.LayerGeneratingProcessor; +import org.openide.filesystems.annotations.LayerGenerationException; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Tomas Zezula + */ +@ServiceProvider(service=Processor.class) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class EmbeddingProviderRegistrationProcessor extends LayerGeneratingProcessor { + + @Override + public Set getSupportedAnnotationTypes() { + return Collections.singleton(EmbeddingProvider.Registration.class.getCanonicalName()); + } + + @Override + protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) throws LayerGenerationException { + for (Element e : roundEnv.getElementsAnnotatedWith(EmbeddingProvider.Registration.class)) { + if (!e.getKind().isClass()) { + throw new LayerGenerationException("Annotated Element has to be a class.", e); //NOI18N + } + final EmbeddingProvider.Registration reg = e.getAnnotation(EmbeddingProvider.Registration.class); + String mimeType = reg.mimeType(); + if (mimeType == null) { + throw new LayerGenerationException("Mime type has to be given.", e); //NOI18N + } else if (!mimeType.isEmpty()) { + mimeType = '/' + mimeType; //NOI18N + } + String targetMimeType = reg.targetMimeType(); + if (targetMimeType == null || targetMimeType.isEmpty()) { + throw new LayerGenerationException("Target mime type has to be given.", e); //NOI18N + } + layer(e). + instanceFile("Editors" + mimeType, null, null). //NOI18N + stringvalue("instanceOf", TaskFactory.class.getName()). ///NOI18N + methodvalue("instanceCreate", EmbeddingProviderFactory.class.getName(), "create"). //NOI18N + stringvalue(EmbeddingProviderFactory.ATTR_TARGET_MIME_TYPE, targetMimeType). + instanceAttribute(EmbeddingProviderFactory.ATTR_PROVIDER, EmbeddingProvider.class). + write(); + } + return true; + } + +} diff --git a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java --- a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java +++ b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java @@ -1398,7 +1398,7 @@ } } - Collection> eifInfos = IndexerCache.getEifCache().getIndexersFor(mimeType, true); + Collection> eifInfos = collectEmbeddingIndexers(mimeType); for(IndexerCache.IndexerInfo info : eifInfos) { try { EmbeddingIndexerFactory factory = info.getIndexerFactory(); @@ -1446,6 +1446,23 @@ } } + @NonNull + private static Collection> collectEmbeddingIndexers( + @NonNull final String topMimeType){ + final Collection> result = new ArrayDeque>(); + collectEmbeddingIndexers(topMimeType, result); + return result; + } + + private static void collectEmbeddingIndexers( + @NonNull final String mimeType, + @NonNull final Collection> collector) { + collector.addAll(IndexerCache.getEifCache().getIndexersFor(mimeType, true)); + for (EmbeddingProviderFactory epf : MimeLookup.getLookup(MimePath.get(mimeType)).lookupAll(EmbeddingProviderFactory.class)) { + collectEmbeddingIndexers(epf.getTargetMimeType(), collector); + } + } + /* test */ void scheduleWork(Iterable multipleWork) { recordCaller(); diff --git a/parsing.api/src/org/netbeans/modules/parsing/spi/EmbeddingProvider.java b/parsing.api/src/org/netbeans/modules/parsing/spi/EmbeddingProvider.java --- a/parsing.api/src/org/netbeans/modules/parsing/spi/EmbeddingProvider.java +++ b/parsing.api/src/org/netbeans/modules/parsing/spi/EmbeddingProvider.java @@ -42,9 +42,14 @@ package org.netbeans.modules.parsing.spi; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.List; import org.netbeans.modules.parsing.api.Embedding; import org.netbeans.modules.parsing.api.Snapshot; +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport; /** @@ -83,6 +88,30 @@ * @return priority of this source provider */ public abstract int getPriority (); + + /** + * Registration of the {@link EmbeddingProvider}. + * Creates a mime lookup registration of the {@link TaskFactory} for + * annotated {@link EmbeddingProvider}. It also provides the target + * mime type of the created embedding which allows the {@link QuerySupport} + * to correctly mark dirty embedded indexers. + * + * @since 1.57 + */ + @Retention(RetentionPolicy.SOURCE) + @Target(ElementType.TYPE) + public @interface Registration { + + /** + * Mime type to which should be the given {@link EmbeddingProvider} registered. + */ + public String mimeType(); + + /** + * Mime type of the embedding created by the registered {@link EmbeddingProvider} + */ + String targetMimeType(); + } } diff --git a/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/EmbeddedIndexerTest.java b/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/EmbeddedIndexerTest.java --- a/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/EmbeddedIndexerTest.java +++ b/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/EmbeddedIndexerTest.java @@ -41,13 +41,8 @@ */ package org.netbeans.modules.parsing.impl.indexing; -import java.awt.Color; -import java.awt.Font; -import java.beans.PropertyChangeEvent; import java.io.File; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -57,29 +52,21 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JEditorPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeListener; -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; import javax.swing.text.Document; import javax.swing.text.EditorKit; -import javax.swing.text.Element; -import javax.swing.text.Style; import javax.swing.text.StyledDocument; import org.netbeans.api.annotations.common.NonNull; -import org.netbeans.api.editor.EditorRegistry; import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.api.editor.mimelookup.test.MockMimeLookup; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.GlobalPathRegistry; -import org.netbeans.editor.AtomicLockEvent; -import org.netbeans.editor.BaseDocument; import org.netbeans.editor.GuardedDocument; import org.netbeans.junit.MockServices; import org.netbeans.junit.NbTestCase; @@ -91,13 +78,12 @@ import org.netbeans.modules.parsing.api.Source; import org.netbeans.modules.parsing.api.Task; import org.netbeans.modules.parsing.api.UserTask; +import org.netbeans.modules.parsing.impl.EmbeddingProviderFactory; import org.netbeans.modules.parsing.spi.EmbeddingProvider; import org.netbeans.modules.parsing.spi.ParseException; import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.parsing.spi.ParserFactory; -import org.netbeans.modules.parsing.spi.SchedulerTask; import org.netbeans.modules.parsing.spi.SourceModificationEvent; -import org.netbeans.modules.parsing.spi.TaskFactory; import org.netbeans.modules.parsing.spi.indexing.Context; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; @@ -123,12 +109,10 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.nodes.Node.Cookie; import org.openide.text.DataEditorSupport; import org.openide.text.NbDocument; import org.openide.util.Exceptions; import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; import org.openide.util.test.TestFileUtils; /** @@ -159,10 +143,13 @@ final FileObject wd = FileUtil.toFileObject(_wd); final FileObject cache = wd.createFolder("cache"); //NOI18N CacheFolder.setCacheFolder(cache); + final Map attrMap = new HashMap(); + attrMap.put(EmbeddingProviderFactory.ATTR_TARGET_MIME_TYPE, MIME_INNER); + attrMap.put(EmbeddingProviderFactory.ATTR_PROVIDER, new TopToInnerEmbProvider()); MockMimeLookup.setInstances( MimePath.get(MIME_TOP), new TopParser.Factory(), - new TopToInnerEmbProvider.Factory(), + EmbeddingProviderFactory.create(attrMap), new TopIndexer.Factory()); MockMimeLookup.setInstances( MimePath.get(MIME_INNER), @@ -179,7 +166,7 @@ " < A> < >")); //NOI18N FileUtil.setMIMEType(EXT_TOP, MIME_TOP); RepositoryUpdaterTest.setMimeTypes(MIME_TOP, MIME_INNER); - ClassPathProviderImpl.root = srcRoot; + ClassPathProviderImpl.setRoot(srcRoot); RepositoryUpdaterTest.waitForRepositoryUpdaterInit(); } @@ -193,7 +180,7 @@ super.tearDown(); } - public void testEmbeddingIndexer() throws Exception { + public void testEmbeddingIndexerQueryOnOuterAndInner() throws Exception { RepositoryUpdater ru = RepositoryUpdater.getDefault(); assertEquals(0, ru.getScannedBinaries().size()); assertEquals(0, ru.getScannedBinaries().size()); @@ -206,6 +193,8 @@ srcCp = ClassPath.getClassPath(srcRoot, PATH_TOP_SOURCES); assertNotNull(srcCp); + assertEquals(1, srcCp.getRoots().length); + assertEquals(srcRoot, srcCp.getRoots()[0]); globalPathRegistry_register(PATH_TOP_SOURCES, srcCp); assertTrue (handler.await()); assertEquals(0, handler.getBinaries().size()); @@ -267,14 +256,95 @@ assertEquals(1,res.size()); assertEquals(Boolean.TRUE.toString(), res.iterator().next().getValue("valid")); //NOI18N -// sup = QuerySupport.forRoots(InnerIndexer.NAME, InnerIndexer.VERSION, srcRoot); -// res = sup.query("_sn", srcFile.getNameExt(), QuerySupport.Kind.EXACT, (String[]) null); -// assertEquals(5,res.size()); -// count = countModes(res); -// assertEquals(Integer.valueOf(1), count.get(0)); -// assertEquals(Integer.valueOf(2), count.get(1)); -// assertEquals(Integer.valueOf(1), count.get(2)); -// assertEquals(Integer.valueOf(1), count.get(3)); + sup = QuerySupport.forRoots(InnerIndexer.NAME, InnerIndexer.VERSION, srcRoot); + res = sup.query("_sn", srcFile.getNameExt(), QuerySupport.Kind.EXACT, (String[]) null); + assertEquals(5,res.size()); + count = countModes(res); + assertEquals(Integer.valueOf(1), count.get(0)); + assertEquals(Integer.valueOf(2), count.get(1)); + assertEquals(Integer.valueOf(1), count.get(2)); + assertEquals(Integer.valueOf(1), count.get(3)); + } + + public void testEmbeddingIndexerQueryOnInnerOnly() throws Exception { + RepositoryUpdater ru = RepositoryUpdater.getDefault(); + assertEquals(0, ru.getScannedBinaries().size()); + assertEquals(0, ru.getScannedBinaries().size()); + assertEquals(0, ru.getScannedUnknowns().size()); + + final RepositoryUpdaterTest.TestHandler handler = new RepositoryUpdaterTest.TestHandler(); + final Logger logger = Logger.getLogger(RepositoryUpdater.class.getName()+".tests"); + logger.setLevel (Level.FINEST); + logger.addHandler(handler); + + srcCp = ClassPath.getClassPath(srcRoot, PATH_TOP_SOURCES); + assertNotNull(srcCp); + assertEquals(1, srcCp.getRoots().length); + assertEquals(srcRoot, srcCp.getRoots()[0]); + globalPathRegistry_register(PATH_TOP_SOURCES, srcCp); + assertTrue (handler.await()); + assertEquals(0, handler.getBinaries().size()); + assertEquals(1, handler.getSources().size()); + assertEquals(srcRoot.toURL(), handler.getSources().get(0)); + + QuerySupport sup = QuerySupport.forRoots(TopIndexer.NAME, TopIndexer.VERSION, srcRoot); + Collection res = sup.query("_sn", srcFile.getNameExt(), QuerySupport.Kind.EXACT, (String[]) null); + assertEquals(1,res.size()); + assertEquals(Boolean.TRUE.toString(), res.iterator().next().getValue("valid")); //NOI18N + + sup = QuerySupport.forRoots(InnerIndexer.NAME, InnerIndexer.VERSION, srcRoot); + res = sup.query("_sn", srcFile.getNameExt(), QuerySupport.Kind.EXACT, (String[]) null); + assertEquals(4,res.size()); + Map count = countModes(res); + assertEquals(Integer.valueOf(1), count.get(0)); + assertEquals(Integer.valueOf(2), count.get(1)); + assertEquals(Integer.valueOf(1), count.get(2)); + + //Symulate EditorRegistry + final Source src = Source.create(srcFile); + ParserManager.parse(Collections.singleton(src), new UserTask() { + @Override + public void run(ResultIterator resultIterator) throws Exception { + } + }); + final DataObject dobj = DataObject.find(srcFile); + final EditorCookie ec = dobj.getLookup().lookup(EditorCookie.class); + final StyledDocument doc = ec.openDocument(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + final JEditorPane jp = new JEditorPane() { + @Override + public boolean isFocusOwner() { + return true; + } + }; + jp.setDocument(doc); + EditorApiPackageAccessor.get().register(jp); + } + }); + + //Do modification + NbDocument.runAtomic(doc, new Runnable() { + @Override + public void run() { + try { + doc.insertString(doc.getLength(), "", null); //NOI18N + } catch (Exception e) { + Exceptions.printStackTrace(e); + } + } + }); + + //Query should be updated + sup = QuerySupport.forRoots(InnerIndexer.NAME, InnerIndexer.VERSION, srcRoot); + res = sup.query("_sn", srcFile.getNameExt(), QuerySupport.Kind.EXACT, (String[]) null); + assertEquals(5,res.size()); + count = countModes(res); + assertEquals(Integer.valueOf(1), count.get(0)); + assertEquals(Integer.valueOf(2), count.get(1)); + assertEquals(Integer.valueOf(1), count.get(2)); + assertEquals(Integer.valueOf(1), count.get(3)); } private static Map countModes(@NonNull final Collection docs) { @@ -399,6 +469,9 @@ } else if (text.charAt(i) == 'B') { res.setMode(InnerResult.B); break; + } else if (text.charAt(i) == 'C') { + res.setMode(InnerResult.C); + break; } } resultCache = res; @@ -480,14 +553,6 @@ @Override public void cancel() { } - - public static class Factory extends TaskFactory { - @Override - public Collection create(Snapshot snapshot) { - return Collections.singleton(new TopToInnerEmbProvider()); - } - - } } public static class TopIndexer extends EmbeddingIndexer { @@ -525,7 +590,6 @@ @Override public void filesDirty(Iterable dirty, Context context) { - System.out.println("FILES DIRTY!"); try { final IndexingSupport is = IndexingSupport.getInstance(context); for (Indexable df : dirty) { @@ -591,7 +655,6 @@ @Override public void filesDirty(Iterable dirty, Context context) { - System.out.println("INNER DIRTY"); try { final IndexingSupport is = IndexingSupport.getInstance(context); for (Indexable df : dirty) { @@ -646,24 +709,27 @@ public static class ClassPathProviderImpl implements ClassPathProvider { - static volatile FileObject root; + //@GuardedBy("ClassPathProviderImpl.class") + private static FileObject root; + //@GuardedBy("ClassPathProviderImpl.class") + private static ClassPath cp; - private final AtomicReference cpRef = new AtomicReference(); + static synchronized void setRoot(@NonNull final FileObject r) { + cp = null; + root = r; + } @Override public ClassPath findClassPath(FileObject file, String type) { - if (PATH_TOP_SOURCES.equals(type) && - (FileUtil.isParentOf(root, file) || root.equals(file))) { - ClassPath cp = cpRef.get(); - if (cp == null) { - cp = ClassPathSupport.createClassPath(root); - if (!cpRef.compareAndSet(null, cp)) { - cp = cpRef.get(); + synchronized(ClassPathProviderImpl.class) { + if (PATH_TOP_SOURCES.equals(type) && + (FileUtil.isParentOf(root, file) || root.equals(file))) { + if (cp == null) { + cp = ClassPathSupport.createClassPath(root); } - } - assert cp != null; - return cp; + return cp; + } } return null; }