/*******************************************************************************
* Copyright (c) 2012 Sierra Wireless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.koneki.ldt.ui.internal.editor.text;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.parser.IModuleDeclaration;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.SourceParserUtil;
import org.eclipse.dltk.ui.editor.highlighting.AbortSemanticHighlightingException;
import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlighter;
import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlighterExtension;
import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlightingRequestor;
import org.eclipse.dltk.ui.editor.highlighting.SemanticHighlighting;
import org.eclipse.koneki.ldt.core.LuaNature;
import org.eclipse.koneki.ldt.core.internal.ast.models.LuaASTUtils;
import org.eclipse.koneki.ldt.core.internal.ast.models.api.Item;
import org.eclipse.koneki.ldt.core.internal.ast.models.api.LuaFileAPI;
import org.eclipse.koneki.ldt.core.internal.ast.models.common.LuaSourceRoot;
import org.eclipse.koneki.ldt.core.internal.ast.models.file.Identifier;
import org.eclipse.koneki.ldt.ui.internal.Activator;
public class LuaSemanticUpdateWorker extends ASTVisitor implements ISemanticHighlighter, ISemanticHighlighterExtension {
private static final String HL_LOCAL_VARIABLE = ILuaColorConstants.LUA_LOCAL_VARIABLE;
private static final String HL_GLOBAL_VARIABLE = ILuaColorConstants.LUA_GLOBAL_VARIABLE;
private ISemanticHighlightingRequestor requestor;
public SemanticHighlighting[] getSemanticHighlightings() {
return new SemanticHighlighting[] { new LuaSemanticHighlighting(ILuaColorConstants.LUA_LOCAL_VARIABLE, null),
new LuaSemanticHighlighting(ILuaColorConstants.LUA_GLOBAL_VARIABLE, null) };
}
public boolean visitGeneral(ASTNode node) throws Exception {
if (node instanceof LuaSourceRoot) {
// no semantic highlighting if the code is in error.
return !((LuaSourceRoot) node).hasError();
}
if (node instanceof LuaFileAPI) {
// no need to try to do semantic highlighting for APIs...
return false;
}
if (node instanceof Identifier) {
// TODO BUG ECLIPSE 381703 every node should have a definition
final Item item = ((Identifier) node).getDefinition();
if (item != null) {
if (LuaASTUtils.isLocal(item)) {
requestor.addPosition(node.sourceStart(), node.sourceEnd(), HL_LOCAL_VARIABLE);
} else if (LuaASTUtils.isUnresolvedGlobal(item) || LuaASTUtils.isGlobal(item)) {
requestor.addPosition(node.sourceStart(), node.sourceEnd(), HL_GLOBAL_VARIABLE);
}
} else {
final String message = "{0} starting at offset {1} with length {2} has no definition."; //$NON-NLS-1$
final String formattedMessage = MessageFormat.format(message, node.getClass().getName(), node.matchStart(), node.matchLength());
Activator.logWarning(formattedMessage);
}
}
return true;
}
public String[] getHighlightingKeys() {
final Set<String> result = new HashSet<String>();
for (SemanticHighlighting highlighting : getSemanticHighlightings()) {
result.add(highlighting.getPreferenceKey());
}
return result.toArray(new String[result.size()]);
}
public void process(IModuleSource code, ISemanticHighlightingRequestor req) {
this.requestor = req;
try {
((ModuleDeclaration) parseCode(code)).traverse(this);
} catch (ModelException e) {
throw new AbortSemanticHighlightingException();
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
throw new AbortSemanticHighlightingException();
}
}
/**
* @param code
* @return
* @throws ModelException
*/
protected IModuleDeclaration parseCode(IModuleSource code) throws ModelException {
if (code instanceof ISourceModule) {
return parseSourceModule((ISourceModule) code);
} else {
return parseSourceCode(code);
}
}
private IModuleDeclaration parseSourceCode(IModuleSource code) {
return SourceParserUtil.parse(code, LuaNature.ID, null);
}
private IModuleDeclaration parseSourceModule(final ISourceModule sourceModule) {
return SourceParserUtil.parse(sourceModule, null);
}
}