/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed 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 com.vladsch.idea.multimarkdown.spellchecking;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.spellchecker.inspections.IdentifierSplitter;
import com.intellij.spellchecker.tokenizer.TokenConsumer;
import com.intellij.spellchecker.tokenizer.Tokenizer;
import com.vladsch.idea.multimarkdown.psi.MultiMarkdownNamedElement;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class MultiMarkdownIdentifierTokenizer extends Tokenizer<MultiMarkdownNamedElement> {
@Override
public void tokenize(@NotNull MultiMarkdownNamedElement element, TokenConsumer consumer) {
StringBuilder text = new StringBuilder(element.getTextLength());
int offset = -1;
int nodeOffset = -1;
int firstOffset = -1;
int lastOffset = -1;
// extract a range of spell checkable elements, leave out any leading/trailing non-checkable
// and any non-checkable in the middle replace with spaces
for (ASTNode astNode : element.getNode().getChildren(null)) {
if (!MultiMarkdownSpellcheckingStrategy.NO_SPELL_CHECK_SET.contains(astNode.getElementType())) {
offset = astNode.getStartOffset();
if (firstOffset < 0) firstOffset = offset;
else if (lastOffset < offset) appendSpaces(text, offset - lastOffset);
text.append(astNode.getChars());
lastOffset = offset + astNode.getTextLength();
}
if (nodeOffset < 0) {
nodeOffset = offset >= 0 ? offset : astNode.getStartOffset();
}
}
if (nodeOffset < 0) {
// leaf element, take all text, if it is not to be spell checked then should not be here
String elemText = element.getText();
consumer.consumeToken(element, elemText, true, 0, TextRange.allOf(elemText), IdentifierSplitter.getInstance());
} else if (firstOffset >= 0) {
consumer.consumeToken(element, text.toString(), true, firstOffset - element.getNode().getStartOffset(), TextRange.create(0, lastOffset - firstOffset), IdentifierSplitter.getInstance());
}
}
public interface SpellCheckConsumer {
void consume(String word, boolean spellCheck);
}
// used during spell check corrections to create variations that preserve non-spell checkable text
public void tokenizeSpellingSuggestions(@NotNull MultiMarkdownNamedElement element, SpellCheckConsumer consumer) {
// extract a range of spell checkable elements, leave out any leading/trailing non-checkable
// and any non-checkable in the middle replace with spaces
boolean hadChildren = false;
for (ASTNode astNode : element.getNode().getChildren(null)) {
hadChildren = true;
consumer.consume(astNode.getText(), !MultiMarkdownSpellcheckingStrategy.NO_SPELL_CHECK_SET.contains(astNode.getElementType()));
}
if (!hadChildren) {
// leaf element, take all text, if it is not to be spell checked then should not be here
consumer.consume(element.getText(), true);
}
}
private void appendSpaces(StringBuilder text, int i) {
while (i-- > 0) {
text.append(' ');
}
}
}