blob: d3a8efa4b5d74b15207c34d03300dee703c5fd92 [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.php.editor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
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;
import org.netbeans.modules.php.editor.lexer.PHPTokenId;
import org.netbeans.modules.php.editor.parser.GSFPHPParser;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
/**
* Provides model for html code.
*
* @author Marek Fukala
*/
public class PhpEmbeddingProvider extends EmbeddingProvider {
public static final String GENERATED_CODE = "@@@"; //NOI18N
private static final int MAX_EMBEDDING_LENGTH = 5000000; //cca 5M
private static final Logger LOGGER = Logger.getLogger(PhpEmbeddingProvider.class.getName());
private static final String HTML_MIME_TYPE = "text/html"; //NOI18N
@Override
public List<Embedding> getEmbeddings(Snapshot snapshot) {
if (!GSFPHPParser.PARSE_BIG_FILES) {
FileObject fileObject = snapshot.getSource().getFileObject();
long textSize = getTextSize(fileObject, snapshot);
if (textSize > GSFPHPParser.BIG_FILE_SIZE) {
LOGGER.log(Level.INFO, "Parsing of big file cancelled. Size: {0} Name: {1}",
new Object[] {textSize, fileObject != null ? FileUtil.getFileDisplayName(fileObject) : "<no file>"});
return Collections.emptyList();
}
}
TokenHierarchy<?> th = snapshot.getTokenHierarchy();
TokenSequence<PHPTokenId> sequence = th.tokenSequence(PHPTokenId.language());
//issue #159775 logging >>>
if (sequence == null) {
Logger.getLogger("PhpEmbeddingProvider").log(
Level.WARNING,
"TokenHierarchy.tokenSequence(PhpTokenId.language()) == null " + "for static immutable PHP TokenHierarchy!\nFile = ''{0}'' ;snapshot mimepath=''{1}''",
new Object[]{snapshot.getSource().getFileObject().getPath(), snapshot.getMimePath()});
return Collections.emptyList();
}
//<<< end of the logging
sequence.moveStart();
List<Embedding> embeddings = new ArrayList<>();
//marek (workaround): there seems to be a bug in parsing api - if I create
//the embedding for each PHPTokenId.T_INLINE_HTML token separatelly then the offsets
//translation is broken
int from = -1;
int len = 0;
while (sequence.moveNext()) {
Token t = sequence.token();
if (t.id() == PHPTokenId.T_INLINE_HTML) {
if (from < 0) {
from = sequence.offset();
}
len += t.length();
} else {
if (from >= 0) {
//lets suppose the text is always html :-(
createHtmlEmbedding(embeddings, snapshot, from, len);
//add only one virtual generated token for a sequence of PHP tokens
embeddings.add(snapshot.create(GENERATED_CODE, HTML_MIME_TYPE));
}
from = -1;
len = 0;
}
}
if (from >= 0) {
createHtmlEmbedding(embeddings, snapshot, from, len);
}
if (embeddings.isEmpty()) {
//always embed html even if there isn't any
//this causes the parsing api to run tasks registered to text/html
//even if there isn't any html content
return Collections.singletonList(snapshot.create("", HTML_MIME_TYPE));
} else {
return Collections.singletonList(Embedding.create(embeddings));
}
}
private static void createHtmlEmbedding(List<Embedding> embeddings, Snapshot snapshot, int from, int length) {
assert embeddings != null;
assert snapshot != null;
if (length <= MAX_EMBEDDING_LENGTH) {
embeddings.add(snapshot.create(from, length, HTML_MIME_TYPE)); //NOI18N
} else {
LOGGER.log(Level.FINE, "HTML embedding wasn''t created - from: {0}, length: {1}", new Object[] {from, length});
}
}
@Override
public int getPriority() {
return 110;
}
@Override
public void cancel() {
//do nothing
}
private long getTextSize(@NullAllowed FileObject fileObject, Snapshot snapshot) {
if (fileObject != null) {
return fileObject.getSize();
}
return snapshot.getText().length();
}
public static final class Factory extends TaskFactory {
@Override
public Collection<SchedulerTask> create(final Snapshot snapshot) {
return Collections.<SchedulerTask>singletonList(new PhpEmbeddingProvider());
}
}
}