package bndtools.editor.completion;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.IWhitespaceDetector;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WhitespaceRule;
import aQute.bnd.osgi.Analyzer;
public class BndScanner extends RuleBasedScanner {
BndSourceViewerConfiguration bsvc;
public BndScanner(BndSourceViewerConfiguration manager) {
bsvc = manager;
IRule[] rules = new IRule[] {
new WhitespaceRule(new IWhitespaceDetector() {
public boolean isWhitespace(char c) {
return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
}), new BndWordRule(), new MacroRule(bsvc.T_MACRO), new EndOfLineRule("#", bsvc.T_COMMENT), new BndEndOfLineRule("\\ ", bsvc.T_ERROR), new BndEndOfLineRule("\\\t", bsvc.T_ERROR),
};
setRules(rules);
setDefaultReturnToken(bsvc.T_DEFAULT);
}
class BndWordRule implements IRule {
Map<String,IToken> keyWords = new HashMap<String,IToken>();
public BndWordRule() {
addWords(Analyzer.headers, bsvc.T_INSTRUCTION);
addWords(Analyzer.options, bsvc.T_OPTION);
addWords(Analyzer.directives, bsvc.T_DIRECTIVE);
// TODO need to move these constants to Constants to avoid the
// dependency on aQute.bnd.make.component which drags in half the
// universe
// addWords(ServiceComponent.componentDirectives, bsvc.T_COMPONENT);
}
private boolean isWordStart(char c) {
return Character.isJavaIdentifierStart(c);
}
private boolean isWordPart(char c) {
return Character.isJavaIdentifierPart(c) || c == '-';
}
public IToken evaluate(ICharacterScanner scanner) {
StringBuffer sb = new StringBuffer();
int c = scanner.read();
if (isWordStart((char) c) || c == '-') {
do {
sb.append((char) c);
c = scanner.read();
} while (c != ICharacterScanner.EOF && isWordPart((char) c));
scanner.unread();
IToken token = keyWords.get(sb.toString());
if (token != null)
return token;
return bsvc.T_DEFAULT;
}
scanner.unread();
return Token.UNDEFINED;
}
private void addWords(String[] words, IToken token) {
for (int i = 0; i < words.length; ++i) {
keyWords.put(words[i], token);
}
}
}
class BndEndOfLineRule extends EndOfLineRule {
public BndEndOfLineRule(String startSequence, IToken token) {
super(startSequence, token);
}
@Override
protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {
boolean checkEof = eofAllowed;
if (BndScanner.this.fOffset < BndScanner.this.fDocument.getLength()) {
checkEof = false;
}
return super.sequenceDetected(scanner, sequence, checkEof);
}
}
}