package org.eclipse.dltk.tcl.internal.ui; import java.util.Iterator; import java.util.List; import org.eclipse.dltk.ast.ASTListNode; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.declarations.Argument; import org.eclipse.dltk.ast.declarations.MethodDeclaration; import org.eclipse.dltk.ast.declarations.ModuleDeclaration; import org.eclipse.dltk.ast.declarations.TypeDeclaration; import org.eclipse.dltk.compiler.env.IModuleSource; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.SourceParserUtil; import org.eclipse.dltk.tcl.ast.ComplexString; import org.eclipse.dltk.tcl.ast.StringArgument; import org.eclipse.dltk.tcl.ast.TclArgument; import org.eclipse.dltk.tcl.ast.TclArgumentKind; import org.eclipse.dltk.tcl.ast.TclCommand; import org.eclipse.dltk.tcl.ast.TclModule; import org.eclipse.dltk.tcl.ast.TclModuleDeclaration; import org.eclipse.dltk.tcl.ast.VariableReference; import org.eclipse.dltk.tcl.internal.ui.text.TclTextTools; import org.eclipse.dltk.tcl.parser.TclParser; import org.eclipse.dltk.tcl.parser.TclParserUtils; import org.eclipse.dltk.tcl.parser.TclVisitor; import org.eclipse.dltk.tcl.parser.definitions.DefinitionManager; import org.eclipse.dltk.tcl.ui.TclPreferenceConstants; import org.eclipse.dltk.tcl.ui.semantilhighlighting.ISemanticHighlightingExtension; import org.eclipse.dltk.ui.editor.highlighting.HighlightedPosition; import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlightingRequestor; import org.eclipse.dltk.ui.editor.highlighting.SemanticHighlighting; import org.eclipse.dltk.ui.preferences.PreferencesMessages; import org.eclipse.emf.common.util.EList; public class DefaultTclSemanticHighlightingExtension implements ISemanticHighlightingExtension { private SemanticHighlighting[] highlightings = new SemanticHighlighting[] { new TclTextTools.SH(TclPreferenceConstants.EDITOR_PROCEDURES_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_function_colors), new TclTextTools.SH(TclPreferenceConstants.EDITOR_ARGUMENTS_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_arguments), new TclTextTools.SH(TclPreferenceConstants.EDITOR_CLASSES_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_class_colors), new TclTextTools.SH(TclPreferenceConstants.EDITOR_BASE_CLASS_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_base_classes), new TclTextTools.SH(TclPreferenceConstants.EDITOR_STRING_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_strings), new TclTextTools.SH(TclPreferenceConstants.EDITOR_VARIABLE_COLOR, null, PreferencesMessages.DLTKEditorPreferencePage_variables) }; private static final String HL_PROCEDURES = TclPreferenceConstants.EDITOR_PROCEDURES_COLOR; private static final String HL_ARGUMENTS = TclPreferenceConstants.EDITOR_ARGUMENTS_COLOR; private static final String HL_CLASSES = TclPreferenceConstants.EDITOR_CLASSES_COLOR; private static final String HL_BASE_CLASSES = TclPreferenceConstants.EDITOR_BASE_CLASS_COLOR; private static final String HL_STRINGS = TclPreferenceConstants.EDITOR_STRING_COLOR; private static final String HL_VARIABLES = TclPreferenceConstants.EDITOR_VARIABLE_COLOR; public DefaultTclSemanticHighlightingExtension() { } public HighlightedPosition[] calculatePositions(ASTNode node, ISemanticHighlightingRequestor requestor) { // Check Tcl procedures if (node instanceof MethodDeclaration) { MethodDeclaration m = (MethodDeclaration) node; requestor.addPosition(m.getNameStart(), m.getNameEnd(), HL_PROCEDURES); } // Check procedure arguments if (node instanceof Argument) { Argument m = (Argument) node; requestor.addPosition(m.getNameStart(), m.getNameEnd(), HL_ARGUMENTS); } // Check IncrTcl and XOTcl classes if (node instanceof TypeDeclaration) { TypeDeclaration t = (TypeDeclaration) node; List<ASTNode> children; // Handle base classes highlighting ASTListNode s = t.getSuperClasses(); if (s != null && s.getChilds() != null) { children = s.getChilds(); Iterator<ASTNode> it = children.iterator(); while (it.hasNext()) { ASTNode n = it.next(); requestor.addPosition(n.sourceStart(), n.sourceEnd(), HL_BASE_CLASSES); } } requestor.addPosition(t.getNameStart(), t.getNameEnd(), HL_CLASSES); } return null; } @Override public void processNode(ASTNode node, ISemanticHighlightingRequestor requestor) { calculatePositions(node, requestor); } @Override public SemanticHighlighting[] getHighlightings() { return highlightings; } /** * Perform strings highlighting. * * @since 2.0 */ public void doOtherHighlighting(IModuleSource code, final ISemanticHighlightingRequestor semanticHighlightingRequestor) { IModelElement modelElement = code.getModelElement(); if (modelElement == null) { return; } ModuleDeclaration moduleDeclaration = SourceParserUtil .getModuleDeclaration( (org.eclipse.dltk.core.ISourceModule) modelElement); if (moduleDeclaration instanceof TclModuleDeclaration) { TclModuleDeclaration tclModule = (TclModuleDeclaration) moduleDeclaration; TclModule module = tclModule.getTclModule(); if (module == null) { TclParser parser = new TclParser(); module = parser.parseModule(code.getSourceContents(), null, DefinitionManager.getInstance().createProcessor()); } if (module != null) { TclParserUtils.traverse(module.getStatements(), new TclVisitor() { @Override public boolean visit(StringArgument arg) { String value = arg.getValue(); if (value.startsWith("\"") && value.endsWith("\"")) { // addPosition(arg.getStart(), arg.getEnd(), // highlightingIndex) semanticHighlightingRequestor.addPosition( arg.getStart(), arg.getEnd(), HL_STRINGS); } else { // Look for sub strings int pos = value.indexOf('\"'); while (pos != -1) { int pos2 = value.indexOf('\"', pos + 1); if (pos2 == -1) { break; } // Add region from pos to pos2 semanticHighlightingRequestor .addPosition( arg.getStart() + pos, arg.getStart() + pos2 + 1, HL_STRINGS); pos = value.indexOf('\"', pos2 + 1); } } return super.visit(arg); } @Override public boolean visit(TclCommand command) { TclArgument name = command.getName(); if (name instanceof StringArgument) { String value = ((StringArgument) name) .getValue(); if (value.startsWith("\"") && value.endsWith("\"")) { // addPosition(arg.getStart(), // arg.getEnd(), // highlightingIndex) semanticHighlightingRequestor .addPosition(name.getStart(), name.getEnd(), HL_STRINGS); } } return super.visit(command); } @Override public boolean visit(VariableReference list) { semanticHighlightingRequestor.addPosition( list.getStart(), list.getEnd(), HL_VARIABLES); return super.visit(list); } @Override public boolean visit(ComplexString list) { if (list.getKind() == TclArgumentKind.QUOTED) { EList<TclArgument> arguments = list .getArguments(); // boolean addFirst = false; boolean addLast = false; for (int i = 0; i < arguments.size(); i++) { TclArgument tclArgument = arguments .get(i); if (tclArgument instanceof StringArgument) { semanticHighlightingRequestor .addPosition( tclArgument .getStart(), tclArgument .getEnd(), HL_STRINGS); } if (tclArgument instanceof VariableReference) { semanticHighlightingRequestor .addPosition( tclArgument .getStart(), tclArgument .getEnd(), HL_VARIABLES); if (i == 0) { addFirst = true; } if (i == arguments.size() - 1) { addLast = true; } } if (tclArgument instanceof ComplexString) { visit((ComplexString) tclArgument); } } if (addFirst) { semanticHighlightingRequestor .addPosition(list.getStart(), list.getStart() + 1, HL_STRINGS); } if (addLast) { semanticHighlightingRequestor .addPosition(list.getEnd() - 1, list.getEnd(), HL_STRINGS); } return false; } return super.visit(list); } }); } } } }