blob: 4b6f8e17e8f3572323aa2d15e5bef26a69351d05 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.javascript2.knockout.index;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.javascript2.lexer.api.JsTokenId;
import org.netbeans.modules.parsing.api.Snapshot;
import org.netbeans.modules.parsing.spi.Parser;
import org.netbeans.modules.parsing.spi.indexing.Context;
import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
import org.netbeans.modules.parsing.spi.indexing.Indexable;
import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument;
import org.netbeans.modules.parsing.spi.indexing.support.IndexingSupport;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
import org.openide.util.Parameters;
import org.openide.util.Utilities;
/**
*
* @author Roman Svitanic
*/
public class KnockoutIndexer extends EmbeddingIndexer {
public static final String CUSTOM_ELEMENT = "ce"; //NOI18N
private static final Logger LOG = Logger.getLogger(KnockoutIndexer.class.getName());
private static final ThreadLocal<Map<URI, Collection<KnockoutCustomElement>>> CUSTOM_ELEMENTS = new ThreadLocal<>();
@Override
protected void index(Indexable indexable, Parser.Result parserResult, Context context) {
Map<URI, Collection<KnockoutCustomElement>> cElements = CUSTOM_ELEMENTS.get();
if (cElements != null && !cElements.isEmpty()) {
IndexingSupport support;
try {
support = IndexingSupport.getInstance(context);
} catch (IOException ioe) {
LOG.log(Level.WARNING, null, ioe);
return;
}
try {
Collection<KnockoutCustomElement> elements = cElements.remove(indexable.getURL().toURI());
if (elements != null) {
IndexDocument elementDocument = support.createDocument(indexable);
for (KnockoutCustomElement customElement : elements) {
StringBuilder sb = new StringBuilder();
sb.append(customElement.getName()).append(":"); //NOI18N
sb.append(customElement.getFqn()).append(":"); //NOI18N
sb.append(customElement.getOffset());
if (!customElement.getParameters().isEmpty()) {
sb.append(":"); //NOI18N
for (int i = 0; i < customElement.getParameters().size(); i++) {
sb.append(customElement.getParameters().get(i));
if (i != (customElement.getParameters().size() - 1)) {
sb.append(";"); //NOI18N
}
}
}
elementDocument.addPair(CUSTOM_ELEMENT, sb.toString(), true, true);
}
support.addDocument(elementDocument);
}
} catch (URISyntaxException ex) {
LOG.log(Level.INFO, null, ex);
}
}
}
public static void addCustomElement(final URI uri, final KnockoutCustomElement customElement) {
final Map<URI, Collection<KnockoutCustomElement>> map = CUSTOM_ELEMENTS.get();
if (map == null) {
throw new IllegalStateException("KnockoutIndexer.addCustomElement can be called only from scanner thread."); //NOI18N
}
Collection<KnockoutCustomElement> elements = map.get(uri);
if (elements == null) {
elements = new ArrayList<>();
elements.add(customElement);
map.put(uri, elements);
} else {
elements.add(customElement);
}
}
public static boolean isScannerThread() {
return CUSTOM_ELEMENTS.get() != null;
}
public static final class Factory extends EmbeddingIndexerFactory {
public static final String NAME = "knockoutjs"; // NOI18N
public static final int VERSION = 1;
private static final int PRIORITY = 220;
private static final ThreadLocal<Collection<Runnable>> postScanTasks = new ThreadLocal<>();
@Override
public EmbeddingIndexer createIndexer(Indexable indexable, Snapshot snapshot) {
if (isIndexable(indexable, snapshot)) {
return new KnockoutIndexer();
} else {
return null;
}
}
@Override
public void filesDeleted(Iterable<? extends Indexable> deleted, Context context) {
try {
IndexingSupport is = IndexingSupport.getInstance(context);
for (Indexable i : deleted) {
is.removeDocuments(i);
}
} catch (IOException ioe) {
LOG.log(Level.WARNING, null, ioe);
}
}
@Override
public void filesDirty(Iterable<? extends Indexable> dirty, Context context) {
}
@Override
public String getIndexerName() {
return NAME;
}
@Override
public int getIndexVersion() {
return VERSION;
}
private boolean isIndexable(Indexable indexable, Snapshot snapshot) {
return JsTokenId.JAVASCRIPT_MIME_TYPE.equals(snapshot.getMimeType());
}
@Override
public boolean scanStarted(Context context) {
postScanTasks.set(new LinkedList<Runnable>());
CUSTOM_ELEMENTS.set(new HashMap<URI, Collection<KnockoutCustomElement>>());
return super.scanStarted(context);
}
@Override
public void scanFinished(Context context) {
try {
for (Runnable task : postScanTasks.get()) {
task.run();
}
} finally {
postScanTasks.remove();
super.scanFinished(context);
}
}
public static boolean isScannerThread() {
return postScanTasks.get() != null;
}
public static void addPostScanTask(final Runnable task) {
Parameters.notNull("task", task); //NOI18N
final Collection<Runnable> tasks = postScanTasks.get();
if (tasks == null) {
throw new IllegalStateException("JsIndexer.postScanTask can be called only from scanner thread."); //NOI18N
}
tasks.add(task);
}
@Override
public int getPriority() {
return PRIORITY;
}
}
}