From 4cc61d0449ed463408633016759694bc59badc04 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Mon, 21 Sep 2015 11:16:56 -0400 Subject: [PATCH] Bug 477962 - Create Basic QML Editor with Syntax Highlighting Added a QML Editor which handles basic syntax highlighting for keywords, multi-line and single-line comments, and strings. The highlight colours are similar to that of Qt Creator and cannot be modified by users as of yet. Change-Id: Ied0ab0432a3a2a43f93733964747c792e29771c4 Signed-off-by: Matthew Bastien --- qt/org.eclipse.cdt.qt.ui/plugin.properties | 2 + qt/org.eclipse.cdt.qt.ui/plugin.xml | 18 +++ .../editor/QMLDocumentSetupParticipant.java | 33 ++++ .../cdt/internal/qt/ui/editor/QMLEditor.java | 26 ++++ .../internal/qt/ui/editor/QMLKeywords.java | 119 ++++++++++++++ .../qt/ui/editor/QMLPartitionScanner.java | 46 ++++++ .../internal/qt/ui/text/IQMLPartitions.java | 29 ++++ .../ui/text/QMLSourceViewerConfiguration.java | 145 ++++++++++++++++++ 8 files changed, 418 insertions(+) create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLDocumentSetupParticipant.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLEditor.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLKeywords.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLPartitionScanner.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/IQMLPartitions.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/QMLSourceViewerConfiguration.java diff --git a/qt/org.eclipse.cdt.qt.ui/plugin.properties b/qt/org.eclipse.cdt.qt.ui/plugin.properties index f27ceb8ace4..0cf254ce126 100644 --- a/qt/org.eclipse.cdt.qt.ui/plugin.properties +++ b/qt/org.eclipse.cdt.qt.ui/plugin.properties @@ -7,6 +7,8 @@ pluginName=C/C++ Qt Support UI providerName=Eclipse CDT +qmlEditor.name=QML Editor + qtHighlighting.extName=Qt Semantic Highlighting qtHighlighting.displayName=Qt Keywords diff --git a/qt/org.eclipse.cdt.qt.ui/plugin.xml b/qt/org.eclipse.cdt.qt.ui/plugin.xml index 8e9f4f0402c..617838eac83 100644 --- a/qt/org.eclipse.cdt.qt.ui/plugin.xml +++ b/qt/org.eclipse.cdt.qt.ui/plugin.xml @@ -47,4 +47,22 @@ project="true"> + + + + + + + + diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLDocumentSetupParticipant.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLDocumentSetupParticipant.java new file mode 100644 index 00000000000..0b29fb244da --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLDocumentSetupParticipant.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.editor; + +import org.eclipse.cdt.internal.qt.ui.text.IQMLPartitions; +import org.eclipse.core.filebuffers.IDocumentSetupParticipant; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; + +public class QMLDocumentSetupParticipant implements IDocumentSetupParticipant, IQMLPartitions { + + @Override + public void setup(IDocument document) { + IDocumentPartitioner partitioner = new FastPartitioner(new QMLPartitionScanner(), IQMLPartitions.ALL_QMLPARTITIONS); + if (document instanceof IDocumentExtension3) { + IDocumentExtension3 ext = (IDocumentExtension3) document; + ext.setDocumentPartitioner(IQMLPartitions.QML_PARTITIONING, partitioner); + } else { + document.setDocumentPartitioner(partitioner); + } + partitioner.connect(document); + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLEditor.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLEditor.java new file mode 100644 index 00000000000..685ea7fdb0b --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLEditor.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.editor; + +import org.eclipse.cdt.internal.qt.ui.text.QMLSourceViewerConfiguration; +import org.eclipse.ui.editors.text.TextEditor; + +/** + * Basic editor for QML. Thus far has only syntax highlighting capabilities. + */ +public class QMLEditor extends TextEditor { + public static final String EDITOR_ID = "org.eclipse.cdt.qt.ui.QMLEditor"; //$NON-NLS-1$ + + @Override + protected void initializeEditor() { + setSourceViewerConfiguration(new QMLSourceViewerConfiguration()); + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLKeywords.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLKeywords.java new file mode 100644 index 00000000000..6e56891803c --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLKeywords.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.editor; + +/** + * Constants for the various keywords used by QML and ECMA Script + */ +public class QMLKeywords { + // QML reserved words + public static final String IMPORT = "import"; //$NON-NLS-1$ + public static final String CONST = "const"; //$NON-NLS-1$ + public static final String PROPERTY = "property"; //$NON-NLS-1$ + public static final String READONLY = "readonly"; //$NON-NLS-1$ + public static final String SIGNAL = "signal"; //$NON-NLS-1$ + public static final String AS = "as"; //$NON-NLS-1$ + public static final String ON = "on"; //$NON-NLS-1$ + public static final String TRUE = "true"; //$NON-NLS-1$ + public static final String FALSE = "false"; //$NON-NLS-1$ + + // QML future reserved words + public static final String TRANSIENT = "transient"; //$NON-NLS-1$ + public static final String SYNCHRONIZED = "synchronized"; //$NON-NLS-1$ + public static final String ABSTRACT = "abstract"; //$NON-NLS-1$ + public static final String VOLATILE = "volatile"; //$NON-NLS-1$ + public static final String NATIVE = "native"; //$NON-NLS-1$ + public static final String GOTO = "goto"; //$NON-NLS-1$ + public static final String BYTE = "byte"; //$NON-NLS-1$ + public static final String LONG = "long"; //$NON-NLS-1$ + public static final String CHAR = "char"; //$NON-NLS-1$ + public static final String SHORT = "short"; //$NON-NLS-1$ + public static final String FLOAT = "float"; //$NON-NLS-1$ + + // QML basic types + public static final String BOOLEAN = "boolean"; //$NON-NLS-1$ + public static final String DOUBLE = "double"; //$NON-NLS-1$ + public static final String INT = "int"; //$NON-NLS-1$ + public static final String LIST = "list"; //$NON-NLS-1$ + public static final String COLOR = "color"; //$NON-NLS-1$ + public static final String REAL = "real"; //$NON-NLS-1$ + public static final String STRING = "string"; //$NON-NLS-1$ + public static final String URL = "url"; //$NON-NLS-1$ + public static final String VAR = "var"; //$NON-NLS-1$ + + // ECMA Script reserved words + public static final String BREAK = "break"; //$NON-NLS-1$ + public static final String DO = "do"; //$NON-NLS-1$ + public static final String INSTANCEOF = "instanceof"; //$NON-NLS-1$ + public static final String TYPEOF = "typeof"; //$NON-NLS-1$ + public static final String CASE = "case"; //$NON-NLS-1$ + public static final String ELSE = "else"; //$NON-NLS-1$ + public static final String NEW = "new"; //$NON-NLS-1$ + public static final String CATCH = "catch"; //$NON-NLS-1$ + public static final String FINALLY = "finally"; //$NON-NLS-1$ + public static final String RETURN = "return"; //$NON-NLS-1$ + public static final String VOID = "void"; //$NON-NLS-1$ + public static final String CONTINUE = "continue"; //$NON-NLS-1$ + public static final String FOR = "for"; //$NON-NLS-1$ + public static final String SWITCH = "switch"; //$NON-NLS-1$ + public static final String WHILE = "while"; //$NON-NLS-1$ + public static final String DEBUGGER = "debugger"; //$NON-NLS-1$ + public static final String FUNCTION = "function"; //$NON-NLS-1$ + public static final String THIS = "this"; //$NON-NLS-1$ + public static final String WITH = "with"; //$NON-NLS-1$ + public static final String DEFAULT = "default"; //$NON-NLS-1$ + public static final String IF = "if"; //$NON-NLS-1$ + public static final String THROW = "throw"; //$NON-NLS-1$ + public static final String DELETE = "delete"; //$NON-NLS-1$ + public static final String IN = "in"; //$NON-NLS-1$ + public static final String TRY = "try"; //$NON-NLS-1$ + + // ECMAScript future reserved words + public static final String CLASS = "class"; //$NON-NLS-1$ + public static final String ENUM = "enum"; //$NON-NLS-1$ + public static final String EXTENDS = "extends"; //$NON-NLS-1$ + public static final String SUPER = "super"; //$NON-NLS-1$ + public static final String EXPORT = "export"; //$NON-NLS-1$ + + // ECMA Script strict-mode future reserved words + public static final String IMPLEMENTS = "implements"; //$NON-NLS-1$ + public static final String LET = "let"; //$NON-NLS-1$ + public static final String PRIVATE = "private"; //$NON-NLS-1$ + public static final String PUBLIC = "public"; //$NON-NLS-1$ + public static final String YIELD = "yield"; //$NON-NLS-1$ + public static final String INTERFACE = "interface"; //$NON-NLS-1$ + public static final String PACKAGE = "package"; //$NON-NLS-1$ + public static final String PROTECTED = "protected"; //$NON-NLS-1$ + public static final String STATIC = "static"; //$NON-NLS-1$ + + /** + * Gets an array containing all of the QML and ECMA Script keywords. + * + * @param strictMode + * Whether or not ECMA Script strict mode is enabled. If true, this adds several reserved keywords to + * the list. + * @return An array of keywords + */ + public static final String[] getKeywords(boolean strictMode) { + if (!strictMode) { + return new String[] { IMPORT, CONST, PROPERTY, READONLY, SIGNAL, AS, ON, TRUE, FALSE, TRANSIENT, SYNCHRONIZED, ABSTRACT, + VOLATILE, NATIVE, GOTO, BYTE, LONG, CHAR, SHORT, FLOAT, BOOLEAN, DOUBLE, INT, LIST, COLOR, REAL, STRING, URL, + VAR, BREAK, DO, INSTANCEOF, TYPEOF, CASE, ELSE, NEW, CATCH, FINALLY, RETURN, VOID, CONTINUE, FOR, SWITCH, WHILE, + DEBUGGER, FUNCTION, THIS, WITH, DEFAULT, IF, THROW, DELETE, IN, TRY, CLASS, ENUM, EXTENDS, SUPER, EXPORT }; + } else { + return new String[] { IMPORT, CONST, PROPERTY, READONLY, SIGNAL, AS, ON, TRUE, FALSE, TRANSIENT, SYNCHRONIZED, ABSTRACT, + VOLATILE, NATIVE, GOTO, BYTE, LONG, CHAR, SHORT, FLOAT, BOOLEAN, DOUBLE, INT, LIST, COLOR, REAL, STRING, URL, + VAR, BREAK, DO, INSTANCEOF, TYPEOF, CASE, ELSE, NEW, CATCH, FINALLY, RETURN, VOID, CONTINUE, FOR, SWITCH, WHILE, + DEBUGGER, FUNCTION, THIS, WITH, DEFAULT, IF, THROW, DELETE, IN, TRY, CLASS, ENUM, EXTENDS, SUPER, EXPORT, + IMPLEMENTS, LET, PRIVATE, PUBLIC, YIELD, INTERFACE, PACKAGE, PROTECTED, STATIC }; + } + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLPartitionScanner.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLPartitionScanner.java new file mode 100644 index 00000000000..4d18097898a --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/editor/QMLPartitionScanner.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.editor; + +import org.eclipse.cdt.internal.qt.ui.text.IQMLPartitions; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; + +/** + * Partitions a QML document into four distinct sections: + *
    + *
  1. multi-line comments
  2. + *
  3. single-line comments
  4. + *
  5. strings
  6. + *
  7. anything else that does not fall under the aforementioned categories
  8. + *
+ */ +public class QMLPartitionScanner extends RuleBasedPartitionScanner implements IQMLPartitions { + + public QMLPartitionScanner() { + super(); + + IToken multiLineComment= new Token(QML_MULTI_LINE_COMMENT); + IToken singleLineComment= new Token(QML_SINGLE_LINE_COMMENT); + IToken string= new Token(QML_STRING); + + setPredicateRules(new IPredicateRule[] { + new MultiLineRule("/*", "*/", multiLineComment, (char) 0, true), //$NON-NLS-1$ //$NON-NLS-2$ + new EndOfLineRule("//", singleLineComment), //$NON-NLS-1$ + new SingleLineRule("\"", "\"", string, '\\', true) //$NON-NLS-2$ //$NON-NLS-1$ + }); + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/IQMLPartitions.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/IQMLPartitions.java new file mode 100644 index 00000000000..8a81f5161bd --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/IQMLPartitions.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.text; + +import org.eclipse.cdt.internal.qt.ui.editor.QMLPartitionScanner; + +/** + * Constants for the various partitions created by {@link QMLPartitionScanner}. + */ +public interface IQMLPartitions { + final String QML_PARTITIONING = "___qml_partitioning"; //$NON-NLS-1$ + final String QML_SINGLE_LINE_COMMENT = "__qml_single_comment"; //$NON-NLS-1$ + final String QML_MULTI_LINE_COMMENT = "__qml_multiline_comment"; //$NON-NLS-1$ + final String QML_STRING = "__qml_string"; //$NON-NLS-1$ + + final String[] ALL_QMLPARTITIONS = { + IQMLPartitions.QML_SINGLE_LINE_COMMENT, + IQMLPartitions.QML_MULTI_LINE_COMMENT, + IQMLPartitions.QML_STRING + }; +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/QMLSourceViewerConfiguration.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/QMLSourceViewerConfiguration.java new file mode 100644 index 00000000000..9f5d0916aa1 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/text/QMLSourceViewerConfiguration.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.text; + +import org.eclipse.cdt.internal.qt.ui.editor.QMLEditor; +import org.eclipse.cdt.internal.qt.ui.editor.QMLKeywords; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.ITokenScanner; +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.WordRule; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; + +/** + * Performs syntax highlighting for the {@link QMLEditor}. + */ +public class QMLSourceViewerConfiguration extends TextSourceViewerConfiguration { + private static final int TOKEN_DEFAULT = 0; + private static final int TOKEN_MULTI_LINE_COMMENT = 1; + private static final int TOKEN_SINGLE_LINE_COMMENT = 2; + private static final int TOKEN_KEYWORD = 3; + private static final int TOKEN_STRING = 4; + private static final int TOKEN_TASK_TAG = 5; + + // Just using Qt Creator defaults-ish for now + // TODO: Add preference page for syntax highlighting + private static final IToken[] allTokens = new IToken[] { + new Token(null), + new Token(new TextAttribute(new Color(Display.getCurrent(), new RGB(0, 155, 200)))), + new Token(new TextAttribute(new Color(Display.getCurrent(), new RGB(0, 155, 200)))), + new Token(new TextAttribute(new Color(Display.getCurrent(), new RGB(155, 155, 0)), null, SWT.BOLD)), + new Token(new TextAttribute(new Color(Display.getCurrent(), new RGB(0, 155, 0)), null, SWT.ITALIC)), + new Token(new TextAttribute(new Color(Display.getCurrent(), new RGB(0, 100, 155)), null, SWT.BOLD)) + }; + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + reconciler.setDocumentPartitioning(IQMLPartitions.QML_PARTITIONING); + + DefaultDamagerRepairer dr; + dr = new DefaultDamagerRepairer(createMultiLineCommentTokenScanner()); + reconciler.setDamager(dr, IQMLPartitions.QML_MULTI_LINE_COMMENT); + reconciler.setRepairer(dr, IQMLPartitions.QML_MULTI_LINE_COMMENT); + + dr = new DefaultDamagerRepairer(createSingleLineCommentTokenScanner()); + reconciler.setDamager(dr, IQMLPartitions.QML_SINGLE_LINE_COMMENT); + reconciler.setRepairer(dr, IQMLPartitions.QML_SINGLE_LINE_COMMENT); + + dr = new DefaultDamagerRepairer(createStringTokenScanner()); + reconciler.setDamager(dr, IQMLPartitions.QML_STRING); + reconciler.setRepairer(dr, IQMLPartitions.QML_STRING); + + dr = new DefaultDamagerRepairer(createDefaultTokenScanner()); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + return reconciler; + } + + private ITokenScanner createMultiLineCommentTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + scanner.setDefaultReturnToken(allTokens[TOKEN_MULTI_LINE_COMMENT]); + scanner.setRules(new IRule[] { createTaskTagRule(allTokens[TOKEN_MULTI_LINE_COMMENT]) }); + return scanner; + } + + private ITokenScanner createSingleLineCommentTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + scanner.setDefaultReturnToken(allTokens[TOKEN_SINGLE_LINE_COMMENT]); + scanner.setRules(new IRule[] { createTaskTagRule(allTokens[TOKEN_SINGLE_LINE_COMMENT]) }); + return scanner; + } + + private ITokenScanner createStringTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + scanner.setDefaultReturnToken(allTokens[TOKEN_STRING]); + return scanner; + } + + private ITokenScanner createDefaultTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + + WordRule wordRule = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isJavaIdentifierStart(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + } + }, allTokens[TOKEN_DEFAULT]); + + // Works decently well for now. However, some keywords like 'color' can also be used as identifiers. Can only fix this with + // semantic highlighting after the parser is completed. + for (String keyword : QMLKeywords.getKeywords(true)) { + wordRule.addWord(keyword, allTokens[TOKEN_KEYWORD]); + } + + scanner.setRules(new IRule[] { wordRule }); + return scanner; + } + + private IRule createTaskTagRule(IToken defaultToken) { + WordRule wordRule = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isJavaIdentifierStart(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + } + }, defaultToken); + + // TODO: Add preference page for task tags + wordRule.addWord("TODO", allTokens[TOKEN_TASK_TAG]); //$NON-NLS-1$ + wordRule.addWord("FIXME", allTokens[TOKEN_TASK_TAG]); //$NON-NLS-1$ + wordRule.addWord("XXX", allTokens[TOKEN_TASK_TAG]); //$NON-NLS-1$ + + return wordRule; + } +}