/*
* Copyright 2012 Amazon Technologies, Inc.
*
* 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://aws.amazon.com/apache2.0
*
* This file 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.amazonaws.eclipse.cloudformation.templates.editor;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jface.text.TextAttribute;
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.IWordDetector;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WhitespaceRule;
import org.eclipse.jface.text.rules.WordRule;
import org.eclipse.swt.SWT;
import com.amazonaws.eclipse.cloudformation.templates.editor.TemplateSourceViewerConfiguration.TemplateColorProvider;
import com.amazonaws.eclipse.cloudformation.templates.schema.IntrinsicFunction;
import com.amazonaws.eclipse.cloudformation.templates.schema.PseudoParameter;
import com.amazonaws.eclipse.cloudformation.templates.schema.TemplateSchemaRules;
public class TemplateScanner extends RuleBasedScanner {
private static final TemplateColorProvider COLOR_PROVIDER = new TemplateColorProvider();
private static final IToken INTRINSIC_FUNCTION_TOKEN = new Token(new TextAttribute(COLOR_PROVIDER.getColor(TemplateColorProvider.PURPLE), null, SWT.BOLD));
private static final IToken PSEUDO_PARAMETER_TOKEN = new Token(new TextAttribute(COLOR_PROVIDER.getColor(TemplateColorProvider.PURPLE), null, SWT.BOLD));
private static final IToken RESOURCE_TYPE_TOKEN = new Token(new TextAttribute(COLOR_PROVIDER.getColor(TemplateColorProvider.PURPLE), null, SWT.BOLD));
private static final IToken KEY_TOKEN = new Token(new TextAttribute(COLOR_PROVIDER.getColor(TemplateColorProvider.GREEN), null, SWT.BOLD));
private static final IToken VALUE_TOKEN = new Token(new TextAttribute(COLOR_PROVIDER.getColor(TemplateColorProvider.BLUE)));
private static final class TemplateWordDetector implements IWordDetector {
private static final Set<Character> SYMBOLS = new HashSet<Character>();
static {
SYMBOLS.add('[');
SYMBOLS.add(']');
SYMBOLS.add('{');
SYMBOLS.add('}');
SYMBOLS.add(',');
SYMBOLS.add(':');
SYMBOLS.add('"');
SYMBOLS.add('\'');
}
public boolean isWordStart(char c) {
if (Character.isWhitespace(c)) return false;
if (SYMBOLS.contains(c)) return false;
return true;
}
public boolean isWordPart(char c) {
if (Character.isWhitespace(c)) return false;
// TODO: This one symbol isn't valid for a word start,
// but is valid for a word part
if (c == ':') return true;
if (SYMBOLS.contains(c)) return false;
return true;
}
}
private static class TemplateWhitespaceDetector implements IWhitespaceDetector {
public boolean isWhitespace(char c) {
return Character.isWhitespace(c);
}
}
private static class TemplateWordRule extends WordRule {
private final IToken keyToken;
public TemplateWordRule(TemplateWordDetector templateWordDetector, IToken keyToken, IToken valueToken, boolean b) {
super(templateWordDetector, valueToken, b);
this.keyToken = keyToken;
}
@Override
public IToken evaluate(ICharacterScanner scanner) {
IToken token = super.evaluate(scanner);
if (token == this.fDefaultToken) {
int c = scanner.read();
int readAhead = 1;
while (c == '"' || c != ICharacterScanner.EOF && Character.isWhitespace((char)c)) {
c = scanner.read();
readAhead++;
}
for (int i = 0; i < readAhead; i++) scanner.unread();
if (((char)c) == ':') return keyToken;
}
return token;
}
}
public TemplateScanner() {
// TODO: Can we really ignore case for CloudFormation templates?
WhitespaceRule whitespaceRule = new WhitespaceRule(new TemplateWhitespaceDetector());
TemplateWordRule templateWordRule = new TemplateWordRule(new TemplateWordDetector(), KEY_TOKEN, VALUE_TOKEN, true);
TemplateSchemaRules schemaRules = TemplateSchemaRules.getInstance();
for (PseudoParameter pseudoParameter : schemaRules.getPseudoParameters()) {
templateWordRule.addWord(pseudoParameter.getName(), PSEUDO_PARAMETER_TOKEN);
}
for (IntrinsicFunction intrinsicFunction : schemaRules.getIntrinsicFuntions()) {
templateWordRule.addWord(intrinsicFunction.getName(), INTRINSIC_FUNCTION_TOKEN);
}
for (String resourceType : schemaRules.getResourceTypeNames()) {
templateWordRule.addWord(resourceType, RESOURCE_TYPE_TOKEN);
}
setRules(new IRule[] {
whitespaceRule,
templateWordRule
});
}
public void dispose() {}
}