package com.aptana.editor.sass.contentassist;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import com.aptana.core.util.StringUtil;
import com.aptana.editor.common.AbstractThemeableEditor;
import com.aptana.editor.css.CSSSourceConfiguration;
import com.aptana.editor.css.contentassist.CSSContentAssistProcessor;
import com.aptana.editor.sass.SassPlugin;
import com.aptana.editor.sass.SassSourceConfiguration;
import com.aptana.parsing.lexer.IRange;
import com.aptana.parsing.lexer.Range;
@SuppressWarnings("restriction")
public class SassContentassistProcessor extends CSSContentAssistProcessor
{
private static final String[] SASS_CHARS = {"-","@"};
private static final String[] LESS_CHARS = {"-","@"};
private boolean isSass = false;
private static final Set<String> SASS_KEYWORDS_SET = new HashSet<String>();
static{
SASS_KEYWORDS_SET.add("@extend");
SASS_KEYWORDS_SET.add("@import");
SASS_KEYWORDS_SET.add("@mixin");
SASS_KEYWORDS_SET.add("@include");
SASS_KEYWORDS_SET.add("@charset");
SASS_KEYWORDS_SET.add("@media");
SASS_KEYWORDS_SET.add("@page");
SASS_KEYWORDS_SET.add("@font-face");
SASS_KEYWORDS_SET.add("@namespace");
SASS_KEYWORDS_SET.add("@for");
SASS_KEYWORDS_SET.add("@function");
SASS_KEYWORDS_SET.add("@return");
}
public SassContentassistProcessor(AbstractThemeableEditor editor)
{
super(editor);
}
@Override
protected ICompletionProposal[] doComputeCompletionProposals(ITextViewer viewer, int offset, char activationChar,
boolean autoActivated)
{
isSass = false;
ICompletionProposal[] result = null;
try
{
String fileName = getFilename();
if(StringUtil.isNotBlank(fileName)){
fileName = fileName.toLowerCase();
}else{
fileName = "";
}
if(fileName.endsWith(".sass")||fileName.endsWith(".scss")){
isSass = true;
}
IDocument document = viewer.getDocument();
if(fileName.endsWith(".sass")){
return computeWordCompletionProposals(offset, PROPERTY_ICON,SASS_CHARS);
}else if(fileName.endsWith(".scss")&&needComputeWord(offset, SASS_CHARS, activationChar, document, new String[]{"$","@"})){
return computeWordCompletionProposals(offset, PROPERTY_ICON,SASS_CHARS);
}else if(fileName.endsWith(".less")&&needComputeWord(offset, LESS_CHARS, activationChar, document, new String[]{"$","@"})){
return computeWordCompletionProposals(offset, PROPERTY_ICON,LESS_CHARS);
}else{
result = super.doComputeCompletionProposals(viewer, offset, activationChar, autoActivated);
if(result==null || result.length<1){
result = computeWordCompletionProposals(offset, PROPERTY_ICON,SASS_CHARS);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return result;
}
private boolean needComputeWord(int offset, String[] chars, char activationChar, IDocument document, String[] specChar){
if(StringUtil.contains(specChar, activationChar+"")){
return true;
}
String prefix = getWordPrefix(offset, chars, document);
if(StringUtil.isNotBlank(prefix)){
for (String str : specChar){
if(prefix.startsWith(str)){
return true;
}
}
}
return false;
}
@Override
protected IRange getLexemeRange(IDocument document, int offset)
{
int startOffset = 0;
try
{
int testOffset = document.get(0, offset).lastIndexOf('}', offset);
// add one because we don't want to include the closing brace
startOffset = (testOffset < 0) ? 0 : testOffset + 1;
}
catch (BadLocationException e)
{
}
int endOffset = offset;
try
{
ITypedRegion region = document.getPartition(offset);
if(region!=null) {
//如果是注释, 则直接返回整个注释范围
if(region.getType().equals(CSSSourceConfiguration.MULTILINE_COMMENT) || region.getType().equals(SassSourceConfiguration.MULTI_LINE_COMMENT)) {
return new Range(region.getOffset(), region.getOffset()+region.getLength());
}
String sassPrefix = SassSourceConfiguration.PREFIX;
String cssPrefix = CSSSourceConfiguration.PREFIX;
String defaultType = IDocument.DEFAULT_CONTENT_TYPE;
if(!region.getType().startsWith(cssPrefix) && !region.getType().startsWith(sassPrefix) && !region.getType().equals(defaultType)) {
//不在css代码内时,尝试 向后退一位取CSS分区
region = document.getPartition(offset-1);
}
if(region.getType().startsWith(cssPrefix) || region.getType().startsWith(sassPrefix) || region.getType().equals(defaultType)) {
//在html中时判断css区域的范围
int start = region.getOffset()-1;
if(start>0) {
String type = document.getContentType(start);
if(type==null || ( !type.equals(defaultType) && !type.startsWith(cssPrefix) && !type.startsWith(sassPrefix) )) {
startOffset = region.getOffset();
}
}
if(document.get(region.getOffset(), region.getLength()).trim().endsWith(":")) {
ITypedRegion nextRegion = document.getPartition(region.getOffset() + region.getLength());
if(nextRegion!=null) {
region = nextRegion;
}
}
endOffset = Math.max(startOffset, region.getOffset() + region.getLength() - 1);
}else {
return null;
}
}
}
catch (BadLocationException e)
{
}
return new Range(startOffset, endOffset);
}
@Override
protected Set<String> computeSpecialWords()
{
if(isSass){
return SASS_KEYWORDS_SET;
}
return Collections.emptySet();
}
protected String getPreferenceNodeQualifier()
{
return SassPlugin.PLUGIN_ID;
}
}