diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 89dd50c4317..d58155356ac 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -48,6 +48,7 @@ public class DOMParserTestSuite extends TestCase { suite.addTestSuite( GCCCompleteParseExtensionsTest.class ); suite.addTestSuite(DOMPreprocessorInformationTest.class); suite.addTest(CommentTests.suite()); + suite.addTest(TaskParserTest.suite()); suite.addTest( CompletionTestSuite.suite() ); return suite; } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TaskParserTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TaskParserTest.java new file mode 100644 index 00000000000..f44ef205a03 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TaskParserTest.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2007 Google, Inc 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: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.core.parser.tests.ast2; + +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.internal.core.pdom.indexer.TodoTaskParser; +import org.eclipse.cdt.internal.core.pdom.indexer.TodoTaskParser.Task; + +public class TaskParserTest extends AST2BaseTest { + + public static TestSuite suite() { + return suite(TaskParserTest.class); + } + + public void testTaskParser() throws Exception { + final char[][] taskTags = new char[][] { + "TODO".toCharArray(), + "TODO(my name):".toCharArray(), + "FIXME".toCharArray() + }; + final int PRIORITY_LOW = 1; + final int PRIORITY_NORMAL = 2; + final int PRIORITY_HIGH = 3; + final int[] taskPriorities = new int[] { + PRIORITY_LOW, + PRIORITY_NORMAL, + PRIORITY_HIGH + }; + final boolean isTaskCaseSensitive = true; + + String code = "/* TODO tag 1\n" + + " * FIXME tag 2\n" + + " */\n" + + "\n" + + "// TODO(my name): tag 3\n" + + "// TODO(his name): tag 4\n" + + "// todo Not a tag\n" + + "// TODO FIXME tag 5\n" + + "\n" + + "const char* x = \"TODO Not a tag\";"; + IASTTranslationUnit tu = parse(code, ParserLanguage.CPP, false, true, true); + TodoTaskParser parser = new TodoTaskParser(taskTags, taskPriorities, isTaskCaseSensitive); + Task[] tasks = parser.parse(tu.getComments()); + + assertEquals(6, tasks.length); + assertEquals("TODO", tasks[0].getTag()); + assertEquals("tag 1", tasks[0].getMessage()); + assertEquals(PRIORITY_LOW, tasks[0].getPriority()); + assertEquals(1, tasks[0].getLineNumber()); + assertEquals(3, tasks[0].getStart()); + assertEquals(13, tasks[0].getEnd()); + + assertEquals("FIXME", tasks[1].getTag()); + assertEquals("tag 2", tasks[1].getMessage()); + assertEquals(PRIORITY_HIGH, tasks[1].getPriority()); + assertEquals(2, tasks[1].getLineNumber()); + + assertEquals("TODO(my name):", tasks[2].getTag()); + assertEquals("tag 3", tasks[2].getMessage()); + assertEquals(PRIORITY_NORMAL, tasks[2].getPriority()); + assertEquals(5, tasks[2].getLineNumber()); + + assertEquals("TODO", tasks[3].getTag()); + assertEquals("(his name): tag 4", tasks[3].getMessage()); + assertEquals(PRIORITY_LOW, tasks[3].getPriority()); + assertEquals(6, tasks[3].getLineNumber()); + + assertEquals("TODO", tasks[4].getTag()); + assertEquals("tag 5", tasks[4].getMessage()); + assertEquals(PRIORITY_LOW, tasks[4].getPriority()); + assertEquals(8, tasks[4].getLineNumber()); + + assertEquals("FIXME", tasks[5].getTag()); + assertEquals("tag 5", tasks[5].getMessage()); + assertEquals(PRIORITY_HIGH, tasks[5].getPriority()); + assertEquals(8, tasks[5].getLineNumber()); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java index 9e7a72cc370..3428f19aba3 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 QNX Software Systems and others. + * Copyright (c) 2000, 2007 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 @@ -46,9 +46,9 @@ public interface ICModelMarker { /** * C model task marker type (value "org.eclipse.cdt.core.task"). * This can be used to recognize task markers in the workspace that correspond to tasks - * specified in C/C++ source comments and detected during translation (for example, 'TO-DO: ...'). + * specified in C/C++ source comments and detected during code indexing (for example, 'TO-DO: ...'). * Tasks are identified by a task tag, which can be customized through CCorePlugin - * option "org.eclipse.cdt.core.translation.taskTag". + * option "org.eclipse.cdt.core.taskTag". */ public static final String TASK_MARKER = CCorePlugin.PLUGIN_ID + ".task"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java index 1863a2ac1bf..2e754ff45ae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation 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 @@ -474,7 +474,7 @@ public interface IProblem /** * Invalid type provided - * Required attribugtes: A_TYPE_NAME + * Required attributes: A_TYPE_NAME * @see #A_TYPE_NAME */ public static final int SEMANTIC_INVALID_TYPE = SEMANTICS_RELATED | 0x007; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 331c297b2da..7b02f5506e7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -101,6 +101,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected final boolean supportDeclspecSpecifiers; protected final IBuiltinBindingsProvider builtinBindingsProvider; + + private IToken lastTokenFromScanner; protected AbstractGNUSourceCodeParser(IScanner scanner, IParserLogService logService, ParserMode parserMode, @@ -253,8 +255,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { * thrown when the scanner.nextToken() yields no tokens */ protected IToken fetchToken() throws EndOfFileException { + IToken value= null; + boolean adjustNextToken= false; try { - IToken value = scanner.nextToken(); + value= scanner.nextToken(); // Put the Comments in the Array for later processing int type = value.getType(); while(type == IToken.tCOMMENT || type == IToken.tBLOCKCOMMENT){ @@ -262,12 +266,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { comments = ASTComment.addComment(comments, comment); value = scanner.nextToken(); type= value.getType(); + adjustNextToken= true; } - return value; } catch (OffsetLimitReachedException olre) { handleOffsetLimitException(olre); - return null; + value= null; } + + if (lastTokenFromScanner != null && adjustNextToken) { + lastTokenFromScanner.setNext(value); + } + lastTokenFromScanner= value; + return value; } protected boolean isCancelled = false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/ITodoTaskUpdater.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/ITodoTaskUpdater.java new file mode 100644 index 00000000000..2d0cf36f5b8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/ITodoTaskUpdater.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2007 Google, Inc 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: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.pdom; + +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.index.IIndexFileLocation; + +public interface ITodoTaskUpdater { + public void updateTasks(IASTComment[] comments, IIndexFileLocation[] files); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index e140d12ca0d..7c583d33d6b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -6,9 +6,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Andrew Ferguson (Symbian) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -103,7 +104,6 @@ import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChange * @author Doug Schaefer */ public class PDOMManager implements IWritableIndexManager, IListener { - private static final class PerInstanceSchedulingRule implements ISchedulingRule { public boolean contains(ISchedulingRule rule) { return rule == this; @@ -113,7 +113,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } } - private final class PCL implements IPreferenceChangeListener { + private final class PCL implements IPreferenceChangeListener, IPropertyChangeListener { private ICProject fProject; public PCL(ICProject prj) { fProject= prj; @@ -123,9 +123,17 @@ public class PDOMManager implements IWritableIndexManager, IListener { onPreferenceChange(fProject, event); } } + public void propertyChange(PropertyChangeEvent event) { + String property = event.getProperty(); + if (property.equals(CCorePreferenceConstants.TODO_TASK_TAGS) || + property.equals(CCorePreferenceConstants.TODO_TASK_PRIORITIES) || + property.equals(CCorePreferenceConstants.TODO_TASK_CASE_SENSITIVE)) { + // Rebuild index if task tag preferences change. + reindex(fProject); + } + } } - private static final String SETTINGS_FOLDER_NAME = ".settings"; //$NON-NLS-1$ private static final QualifiedName dbNameProperty= new QualifiedName(CCorePlugin.PLUGIN_ID, "pdomName"); //$NON-NLS-1$ @@ -659,6 +667,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { fPrefListeners.put(prj, pcl); } IndexerPreferences.addChangeListener(prj, pcl); + Preferences pref = CCorePlugin.getDefault().getPluginPreferences(); + pref.addPropertyChangeListener(pcl); } private void unregisterPreferenceListener(ICProject project) { @@ -666,6 +676,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { PCL pcl= (PCL) fPrefListeners.remove(prj); if (pcl != null) { IndexerPreferences.removeChangeListener(prj, pcl); + Preferences pref = CCorePlugin.getDefault().getPluginPreferences(); + pref.removePropertyChangeListener(pcl); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index 675bfa57db9..857e3ae2661 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -110,13 +110,13 @@ abstract public class PDOMWriter { /** * Fully equivalent to - * addSymbols(IASTTranslationUnit, IWritableIndex, int, true, int, IProgressMonitor). + * addSymbols(IASTTranslationUnit, IWritableIndex, int, true, int, null, IProgressMonitor). * @since 4.0 */ public void addSymbols(IASTTranslationUnit ast, IWritableIndex index, int readlockCount, int configHash, IProgressMonitor pm) throws InterruptedException, CoreException { - addSymbols(ast, index, readlockCount, true, configHash, pm); + addSymbols(ast, index, readlockCount, true, configHash, null, pm); } /** @@ -133,7 +133,7 @@ abstract public class PDOMWriter { */ public void addSymbols(IASTTranslationUnit ast, IWritableIndex index, int readlockCount, boolean flushIndex, - int configHash, IProgressMonitor pm) throws InterruptedException, CoreException { + int configHash, ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException, CoreException { final Map symbolMap= new HashMap(); try { HashSet contextIncludes= new HashSet(); @@ -205,6 +205,10 @@ abstract public class PDOMWriter { index.releaseWriteLock(readlockCount, flushIndex); } fStatistics.fAddToIndexTime+= System.currentTimeMillis()-start; + + if (taskUpdater != null) { + taskUpdater.updateTasks(ast.getComments(), orderedPaths); + } } finally { synchronized(fInfo) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/Messages.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/Messages.java index 6e038fc7413..b76a40774dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/Messages.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/Messages.java @@ -21,6 +21,8 @@ public class Messages extends NLS { public static String PDOMIndexerTask_errorWhileParsing; public static String PDOMIndexerTask_parsingFileTask; public static String PDOMIndexerTask_tooManyIndexProblems; + public static String TodoTaskUpdater_taskFormat; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java index 16f846c4801..b97ea3e2ddd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.indexer; @@ -46,6 +47,7 @@ import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.internal.core.CContentTypes; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndex; +import org.eclipse.cdt.internal.core.pdom.ITodoTaskUpdater; import org.eclipse.cdt.internal.core.pdom.IndexerProgress; import org.eclipse.cdt.internal.core.pdom.PDOMWriter; import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; @@ -155,15 +157,15 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer return null; } ILanguage language = tu.getLanguage(); - if (! (language instanceof AbstractLanguage)) + if (!(language instanceof AbstractLanguage)) return null; CodeReader codeReader = tu.getCodeReader(); if (codeReader == null) { return null; } - - return createAST((AbstractLanguage)language, codeReader, scannerInfo, options, pm); + + return createAST((AbstractLanguage) language, codeReader, scannerInfo, options, pm); } /** @@ -172,7 +174,8 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer * @see #parseTUs(IWritableIndex, int, Collection, Collection, IProgressMonitor) * @since 4.0 */ - abstract protected IASTTranslationUnit createAST(AbstractLanguage lang, CodeReader codeReader, IScannerInfo scanInfo, int options, IProgressMonitor pm) throws CoreException; + abstract protected IASTTranslationUnit createAST(AbstractLanguage lang, CodeReader codeReader, + IScannerInfo scanInfo, int options, IProgressMonitor pm) throws CoreException; /** * Convenience method for subclasses, parses the files calling out to the methods @@ -194,15 +197,17 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } private void internalParseTUs(IWritableIndex index, int readlockCount, Collection sources, Collection headers, IProgressMonitor monitor) throws CoreException, InterruptedException { - int options= 0; + TodoTaskUpdater taskUpdater = new TodoTaskUpdater(); + + int options= AbstractLanguage.OPTION_ADD_COMMENTS; if (checkProperty(IndexerPreferences.KEY_SKIP_ALL_REFERENCES)) { options |= AbstractLanguage.OPTION_SKIP_FUNCTION_BODIES; } for (Iterator iter = fFilesUpFront.iterator(); iter.hasNext();) { String upfront= (String) iter.next(); - parseUpFront(upfront, options, index, readlockCount, monitor); + parseUpFront(upfront, options, index, readlockCount, taskUpdater, monitor); } - + // sources first for (Iterator iter = sources.iterator(); iter.hasNext();) { if (monitor.isCanceled()) @@ -210,7 +215,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer ITranslationUnit tu = (ITranslationUnit) iter.next(); final IIndexFileLocation ifl = IndexLocationFactory.getIFL(tu); if (needToUpdate(ifl, 0)) { - parseTU(ifl, tu, options, index, readlockCount, monitor); + parseTU(ifl, tu, options, index, readlockCount, taskUpdater, monitor); } } @@ -226,7 +231,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer else { ITranslationUnit context= findContext(index, ifl); if (context != null) { - parseTU(ifl, context, options, index, readlockCount, monitor); + parseTU(ifl, context, options, index, readlockCount, taskUpdater, monitor); } } } @@ -242,14 +247,14 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer iter.remove(); } else { - parseTU(ifl, tu, options, index, readlockCount, monitor); + parseTU(ifl, tu, options, index, readlockCount, taskUpdater, monitor); } } } } /** - * Convinience method to check whether a translation unit in the index is outdated + * Convenience method to check whether a translation unit in the index is outdated * with respect to its timestamp. * @throws CoreException * @since 4.0 @@ -271,7 +276,8 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } - private void parseTU(IIndexFileLocation originator, ITranslationUnit tu, int options, IWritableIndex index, int readlockCount, IProgressMonitor pm) throws CoreException, InterruptedException { + private void parseTU(IIndexFileLocation originator, ITranslationUnit tu, int options, IWritableIndex index, + int readlockCount, ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws CoreException, InterruptedException { IPath path= tu.getPath(); try { // skip if no scanner info @@ -291,7 +297,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer IASTTranslationUnit ast= createAST(tu, scanner, options, pm); fStatistics.fParsingTime += System.currentTimeMillis()-start; if (ast != null) { - addSymbols(ast, index, readlockCount, false, configHash, pm); + addSymbols(ast, index, readlockCount, false, configHash, taskUpdater, pm); } } } @@ -307,7 +313,8 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } } - private void parseUpFront(String file, int options, IWritableIndex index, int readlockCount, IProgressMonitor pm) throws CoreException, InterruptedException { + private void parseUpFront(String file, int options, IWritableIndex index, int readlockCount, + ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws CoreException, InterruptedException { file= file.trim(); if (file.length() == 0) { return; @@ -348,7 +355,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer fStatistics.fParsingTime += System.currentTimeMillis()-start; if (ast != null) { - addSymbols(ast, index, readlockCount, false, 0, pm); + addSymbols(ast, index, readlockCount, false, 0, taskUpdater, pm); updateInfo(-1, +1, 0); } } @@ -364,7 +371,7 @@ public abstract class PDOMIndexerTask extends PDOMWriter implements IPDOMIndexer } /** - * Overriders must call super.needToUpdate(). If false is returned + * Overrides must call super.needToUpdate(). If false is returned * this must be passed on to their caller: *
 	 *   if (super.needToUpdate()) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskParser.java
new file mode 100644
index 00000000000..bb24f667119
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskParser.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Google, Inc 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:
+ * 	   Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.core.pdom.indexer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.IASTComment;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.internal.core.CharOperation;
+
+public class TodoTaskParser {
+	private static final Task[] EMPTY_TASK_ARRAY = new Task[0];
+
+	private final char[][] tags;
+	private final int[] priorities;
+	private final boolean isTaskCaseSensitive;
+	private final int[] order;
+
+	public TodoTaskParser(char[][] taskTags, int[] taskPriorities, boolean isTaskCaseSensitive) {
+		assert taskPriorities.length == taskTags.length;
+		this.tags = taskTags;
+		this.priorities = taskPriorities;
+		this.isTaskCaseSensitive = isTaskCaseSensitive;
+
+		// Calculate task checking order that gives preference to the longest matching tag.
+		this.order = new int[taskTags.length];
+		for (int i = 0; i < order.length; i++) {
+			order[i] = i;
+		}
+		// Sort order array in reverse order of tag lengths.
+		// Shell sort algorithm from http://en.wikipedia.org/wiki/Shell_sort
+		for (int inc = order.length / 2; inc > 0; inc /= 2) {
+			for (int i = inc; i < order.length; i++) {
+				for (int j = i;
+						j >= inc && taskTags[order[j - inc]].length < taskTags[order[j]].length;
+						j -= inc) {
+					int temp = order[j];
+					order[j] = order[j - inc];
+					order[j - inc] = temp;
+				}
+			}
+		}
+	}
+
+	public Task[] parse(IASTComment[] comments) {
+		List/**/ tasks = new ArrayList();
+		for (int i = 0; i < comments.length; i++) {
+			IASTComment comment = comments[i];
+			IASTFileLocation location = comment.getFileLocation();
+			parse(comment.getComment(), location.getFileName(), location.getNodeOffset(),
+					location.getStartingLineNumber(), tasks);
+		}
+		if (tasks.isEmpty()) {
+			return EMPTY_TASK_ARRAY;
+		}
+		return (Task[]) tasks.toArray(new Task[tasks.size()]);
+	}
+	
+    private void parse(char[] comment, String filename, int offset, int lineNumber,
+    		List/**/ tasks) {
+        int commentLength = comment.length;
+
+    	int foundTaskIndex = tasks.size();
+    	char previous = comment[1]; // Should be '*' or '/'
+    	for (int i = 2; i < commentLength; i++) {
+    		char[] tag = null;
+			nextTag : for (int j = 0; j < order.length; j++) {
+				int itag = order[j];
+				tag = tags[itag];
+				int tagLength = tag.length;
+				if (tagLength == 0 || i + tagLength > commentLength)
+					continue nextTag;
+	
+				// Ensure tag is not leaded with letter if tag starts with a letter
+				if (isIdentifierStart(tag[0]) && isIdentifierPart(previous)) {
+					continue nextTag;
+				}
+	
+				for (int t = 0; t < tagLength; t++) {
+					int x = i + t;
+					if (x >= commentLength)
+						continue nextTag;
+					char sc = comment[x];
+					char tc = tag[t];
+					if (sc != tc) { 											 // case sensitive check
+						if (isTaskCaseSensitive || Character.toLowerCase(sc) != Character.toLowerCase(tc)) { // case insensitive check
+							continue nextTag;
+						}
+					}
+				}
+				// Ensure tag is not followed with letter if tag finishes with a letter
+				if (i + tagLength < commentLength && isIdentifierPart(comment[i + tagLength - 1])) {
+					if (isIdentifierPart(comment[i + tagLength]))
+						continue nextTag;
+				}
+				
+				Task task = new Task(filename, i, i + tagLength, lineNumber,
+						String.valueOf(tag), "", priorities[itag]); //$NON-NLS-1$
+				tasks.add(task);
+				i += tagLength - 1; // Will be incremented when looping
+				break nextTag;
+			}
+    		previous = comment[i];
+    	}
+
+    	boolean containsEmptyTask = false;
+    	for (int i = foundTaskIndex; i < tasks.size(); i++) {
+    		Task task = (Task) tasks.get(i);
+    		// Retrieve message start and end positions
+    		int msgStart = task.start + task.tag.length();
+    		int maxValue = i + 1 < tasks.size() ?
+    				((Task) tasks.get(i + 1)).start : commentLength;
+    		// At most beginning of next task
+    		if (maxValue < msgStart) {
+    			maxValue = msgStart; // Would only occur if tag is before EOF.
+    		}
+    		int end = -1;
+    		char c;
+    		for (int j = msgStart; j < maxValue; j++) {
+    			if ((c = comment[j]) == '\n' || c == '\r') {
+    				end = j;
+    				break;
+    			}
+    		}
+    		if (end == -1) {
+    			for (int j = maxValue; --j >= msgStart;) {
+    				if ((c = comment[j]) == '*') {
+    					end = j;
+    					break;
+    				}
+    			}
+    			if (end == -1) {
+    				end = maxValue;
+    			}
+    		}
+    		// Trim the message
+    		while (msgStart < end && CharOperation.isWhitespace(comment[end - 1]))
+    			end--;
+    		while (msgStart < end && CharOperation.isWhitespace(comment[msgStart]))
+    			msgStart++;
+    		if (msgStart == end) {
+    			// If the description is empty, we might want to see if two tags
+    			// are not sharing the same message.
+    			// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
+    			containsEmptyTask = true;
+    			continue;
+    		}
+    		// Update the end position of the task
+    		task.end = end;
+    		// Get the message source
+    		int messageLength = end - msgStart;
+    		task.message = String.valueOf(comment, msgStart, messageLength);
+    	}
+
+    	if (containsEmptyTask) {
+    		for (int i = foundTaskIndex; i < tasks.size(); i++) {
+    			Task task1 = (Task) tasks.get(i);
+    			if (task1.message.length() == 0) {
+    				for (int j = i + 1; j < tasks.size(); j++) {
+    	    			Task task2 = (Task) tasks.get(j);
+    					if (task2.message.length() != 0) {
+    						task1.message = task2.message;
+    						task1.end = task2.end;
+    						break;
+    					}
+    				}
+    			}
+    		}
+    	}
+    	
+    	// Add comment offset.
+		for (int i = foundTaskIndex; i < tasks.size(); i++) {
+			Task task = (Task) tasks.get(i);
+			task.lineNumber += getLineOffset(comment, task.start);
+			task.start += offset;
+			task.end += offset;
+		}
+    }
+	
+    /**
+     * Returns zero-based line number for a given character position.
+     */
+	private static int getLineOffset(char[] buffer, int pos) {
+		int count = 0;
+		for (int i = 0; i < pos && i < buffer.length; i++) {
+			if (buffer[i] == '\n') {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	private static boolean isIdentifierStart(char c) {
+		return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'
+				|| Character.isUnicodeIdentifierPart(c);
+	}
+	
+	private static boolean isIdentifierPart(char c) {
+		return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'
+		        || c >= '0' && c <= '9'
+		        || Character.isUnicodeIdentifierPart(c);
+	}
+
+
+	public static class Task {
+		private String fileLocation;
+		private int start;
+		private int end;
+		private int lineNumber;
+		private String tag;
+		private String message;
+		private int priority;
+		
+		Task(String fileLocation, int start, int end, int lineNumber,
+				String tag, String message, int priority) {
+			this.fileLocation = fileLocation;
+			this.start = start;
+			this.end = end;
+			this.lineNumber = lineNumber;
+			this.tag = tag;
+			this.message = message;
+			this.priority = priority;
+		}
+
+		public String getFileLocation() {
+			return fileLocation;
+		}
+
+		public int getStart() {
+			return start;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public int getLineNumber() {
+			return lineNumber;
+		}
+
+		public String getTag() {
+			return tag;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+		public int getPriority() {
+			return priority;
+		}
+	}
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskUpdater.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskUpdater.java
new file mode 100644
index 00000000000..b143dc2775d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TodoTaskUpdater.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Google, Inc 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:
+ * 	   Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.core.pdom.indexer;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CCorePreferenceConstants;
+import org.eclipse.cdt.core.dom.ast.IASTComment;
+import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.model.ICModelMarker;
+import org.eclipse.cdt.internal.core.pdom.ITodoTaskUpdater;
+import org.eclipse.cdt.internal.core.pdom.indexer.TodoTaskParser.Task;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.osgi.util.NLS;
+
+
+public class TodoTaskUpdater implements ITodoTaskUpdater {
+	private static final IMarker[] EMPTY_MARKER_ARRAY = new IMarker[0];
+	private static final String SOURCE_ID = "CDT"; //$NON-NLS-1$
+	private static final String[] TASK_MARKER_ATTRIBUTE_NAMES = {
+		IMarker.MESSAGE, 
+		IMarker.PRIORITY, 
+		IMarker.CHAR_START, 
+		IMarker.CHAR_END, 
+		IMarker.LINE_NUMBER, 
+		IMarker.USER_EDITABLE,
+		IMarker.SOURCE_ID,
+	};
+
+	private final TodoTaskParser taskParser;
+	
+	public TodoTaskUpdater() {
+		String value = CCorePlugin.getOption(CCorePreferenceConstants.TODO_TASK_TAGS);
+		if (value == null) {
+			value = CCorePreferenceConstants.DEFAULT_TASK_TAG;
+		}
+        String[] tags = split(value, ","); //$NON-NLS-1$
+        char[][] taskTags = new char[tags.length][];
+        for (int i = 0; i < tags.length; i++) {
+			taskTags[i] = tags[i].toCharArray();
+		}
+        
+		value = CCorePlugin.getOption(CCorePreferenceConstants.TODO_TASK_PRIORITIES);
+		if (value == null) {
+			value = CCorePreferenceConstants.DEFAULT_TASK_PRIORITY;
+		}
+        String[] priorities = split(value, ","); //$NON-NLS-1$
+        int[] taskPriorities = new int[taskTags.length];
+        for (int i = 0; i < taskPriorities.length; i++) {
+			String priority = i < priorities.length ?
+					priorities[i] : CCorePreferenceConstants.DEFAULT_TASK_PRIORITY;
+			taskPriorities[i] =
+					CCorePreferenceConstants.TASK_PRIORITY_HIGH.equals(priority) ?
+						IMarker.PRIORITY_HIGH :
+					CCorePreferenceConstants.TASK_PRIORITY_LOW.equals(priority) ?
+						IMarker.PRIORITY_LOW : IMarker.PRIORITY_NORMAL;
+		}
+        
+		value = CCorePlugin.getOption(CCorePreferenceConstants.TODO_TASK_CASE_SENSITIVE);
+		if (value == null) {
+			value = CCorePreferenceConstants.DEFAULT_TASK_CASE_SENSITIVE;
+		}
+        boolean isTaskCaseSensitive = Boolean.valueOf(value).booleanValue();
+        taskParser = new TodoTaskParser(taskTags, taskPriorities, isTaskCaseSensitive);
+	}
+
+	public void updateTasks(IASTComment[] comments, IIndexFileLocation[] fileLocations) {
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+		for (int i = 0; i < fileLocations.length; i++) {
+			IIndexFileLocation indexFileLocation = fileLocations[i];
+			String filepath = indexFileLocation.getFullPath();
+			if (filepath != null) {
+				IFile file = workspaceRoot.getFile(new Path(filepath));
+				if (file != null && getTasksFor(file).length != 0) {
+					removeTasksFor(file);
+				}
+			}
+		}
+
+		if (comments.length == 0) {
+			return;
+		}
+
+		Task[] tasks = taskParser.parse(comments);
+
+		String location = null;
+		IFile[] files = null;
+		for (int i = 0; i < tasks.length; i++) {
+			Task task = tasks[i];
+			if (!task.getFileLocation().equals(location)) {
+				location = task.getFileLocation();
+				files = workspaceRoot.findFilesForLocation(new Path(location));
+			}
+			for (int j = 0; j < files.length; j++) {
+				try {
+					applyTask(task, files[j]);
+				} catch (CoreException e) {
+					CCorePlugin.log(e);
+				}
+			}
+		}
+	}
+
+	private void applyTask(Task task, IResource resource) throws CoreException {
+		IMarker marker = resource.createMarker(ICModelMarker.TASK_MARKER);
+		String description = NLS.bind(Messages.TodoTaskUpdater_taskFormat,
+				task.getTag(), task.getMessage());
+		marker.setAttributes(
+			TASK_MARKER_ATTRIBUTE_NAMES,
+			new Object[] { 
+				description,
+				new Integer(task.getPriority()),
+				new Integer(task.getStart()),
+				new Integer(task.getEnd()),
+				new Integer(task.getLineNumber()),
+				Boolean.FALSE,
+				SOURCE_ID
+			});
+	}
+
+	private static IMarker[] getTasksFor(IResource resource) {
+		try {
+			if (resource != null && resource.exists())
+				return resource.findMarkers(ICModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
+		} catch (CoreException e) {
+			CCorePlugin.log(e);
+		}
+		return EMPTY_MARKER_ARRAY;
+	}
+	
+	private static void removeTasksFor(IResource resource) {
+		try {
+			if (resource != null && resource.exists())
+				resource.deleteMarkers(ICModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
+		} catch (CoreException e) {
+			CCorePlugin.log(e);
+		}
+	}
+	
+    private String[] split(String value, String delimiters) {
+        StringTokenizer tokenizer = new StringTokenizer(value, delimiters);
+        int size = tokenizer.countTokens();
+        String[] tokens = new String[size];
+        for (int i = 0; i < size; i++)
+            tokens[i] = tokenizer.nextToken();
+        return tokens;
+    }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/messages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/messages.properties
index 4e288321dcf..4374b778678 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/messages.properties
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/messages.properties
@@ -14,3 +14,6 @@ PDOMImportTask_errorInvalidPDOMVersion=The version of the cdt-index to import fo
 PDOMIndexerTask_parsingFileTask=parsing {0} ({1})
 PDOMIndexerTask_errorWhileParsing=Error while parsing {0}.
 PDOMImportTask_errorInvalidArchive=Invalid Archive: {0}
+
+# {0} - task tag, {1} - task message.
+TodoTaskUpdater_taskFormat={0} {1}
diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml
index 3e392efab47..a27d80570ce 100644
--- a/core/org.eclipse.cdt.core/plugin.xml
+++ b/core/org.eclipse.cdt.core/plugin.xml
@@ -418,7 +418,7 @@
       
    
 
-
+
 
    setOptions.
      * 
@@ -375,26 +360,6 @@ public class CCorePlugin extends Plugin {
      * Note: more options might be added in further releases.
      * 
      * RECOGNIZED OPTIONS:
-     * TRANSLATION / Define the Automatic Task Tags
-     *    When the tag list is not empty, translation will issue a task marker whenever it encounters
-     *    one of the corresponding tags inside any comment in C/C++ source code.
-     *    Generated task messages will include the tag, and range until the next line separator or comment ending.
-     *    Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
-     *    another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
-     *    will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
-     *    by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
-     *    be detected either for tag "ToDo" or "ToDo:").
-     *     - option id:         "org.eclipse.cdt.core.translation.taskTags"
-     *     - possible values:   { "[,]*" } where  is a String without any wild-card or leading/trailing spaces 
-     *     - default:           ""
-     * 
-     * TRANSLATION / Define the Automatic Task Priorities
-     *    In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
-     *    of the task markers issued by the translation.
-     *    If the default is specified, the priority of each task marker is "NORMAL".
-     *     - option id:         "org.eclipse.cdt.core.transltaion.taskPriorities"
-     *     - possible values:   { "[,]*" } where  is one of "HIGH", "NORMAL" or "LOW"
-     *     - default:           ""
      * 
      * CORE / Specify Default Source Encoding Format
      *    Get the encoding format for translated sources. This setting is read-only, it is equivalent
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
index 2387e998fe2..18467738c99 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
@@ -8,6 +8,7 @@
  * Contributors:
  *     QNX Software Systems - Initial API and implementation
  *     Markus Schorn (Wind River Systems)
+ *     Sergey Prigogin (Google) 
  *******************************************************************************/
 package org.eclipse.cdt.core;
 
@@ -15,25 +16,71 @@ package org.eclipse.cdt.core;
 public class CCorePreferenceConstants {
 
 	/**
-	 * Possible configurable option ID.
-	 * @see #getDefaultOptions
+     * 
+     * RECOGNIZED OPTIONS:
+     * Define the Automatic Task Tags
+     *    When the tag list is not empty, indexer will issue a task marker whenever it encounters
+     *    one of the corresponding tags inside any comment in C/C++ source code.
+     *    Generated task messages will include the tag, and range until the next line separator or comment ending.
+     *    Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
+     *    another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
+     *    will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
+     *    by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
+     *    be detected either for tag "ToDo" or "ToDo:").
+     *     - option id:         "org.eclipse.cdt.core.taskTags"
+     *     - possible values:   { "[,]*" } where  is a String without any wild-card or leading/trailing spaces 
+     *     - default:           ""
+     * 
+     * Define the Automatic Task Priorities
+     *    In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
+     *    of the task markers issued by the translation.
+     *    If the default is specified, the priority of each task marker is "normal".
+     *     - option id:         "org.eclipse.cdt.core.taskPriorities"
+     *     - possible values:   { "[,]*" } where  is one of "high", "normal" or "low"
+     *     - default:           ""
+     */
+
+	/**
+	 * Task tags used in code comments.
 	 */
-	public static final String TRANSLATION_TASK_TAGS = CCorePlugin.PLUGIN_ID + ".translation.taskTags"; //$NON-NLS-1$
+	public static final String TODO_TASK_TAGS = CCorePlugin.PLUGIN_ID + ".taskTags"; //$NON-NLS-1$
 
 	/**
 	 * Default task tag
 	 */
 	public static final String DEFAULT_TASK_TAG = "TODO"; //$NON-NLS-1$
 	
+	/**
+	 * Possible configurable option value for TODO_TASK_PRIORITIES.
+	 */
+	public static final String TASK_PRIORITY_NORMAL = "normal"; //$NON-NLS-1$	    
+    /**
+     * Possible configurable option value for TODO_TASK_PRIORITIES.
+     */
+    public static final String TASK_PRIORITY_HIGH = "high"; //$NON-NLS-1$
+    /**
+     * Possible configurable option value for TODO_TASK_PRIORITIES.
+     */
+    public static final String TASK_PRIORITY_LOW = "low"; //$NON-NLS-1$
 	/**
 	 * Default task priority
 	 */
-	public static final String DEFAULT_TASK_PRIORITY = CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL;
+	public static final String DEFAULT_TASK_PRIORITY = TASK_PRIORITY_NORMAL;
+
 	/**
-	 * Possible configurable option ID.
-	 * @see #getDefaultOptions
+	 * Priorities associated with task tags.
 	 */
-	public static final String TRANSLATION_TASK_PRIORITIES = CCorePlugin.PLUGIN_ID + ".translation.taskPriorities"; //$NON-NLS-1$
+	public static final String TODO_TASK_PRIORITIES = CCorePlugin.PLUGIN_ID + ".taskPriorities"; //$NON-NLS-1$
+
+	/**
+	 * Case sensitivity of task tags.
+	 */
+	public static final String TODO_TASK_CASE_SENSITIVE = CCorePlugin.PLUGIN_ID + ".taskCaseSensitive"; //$NON-NLS-1$
+
+	/**
+	 * Default case sensitivity of task tags.
+	 */
+	public static final String DEFAULT_TASK_CASE_SENSITIVE = "false"; //$NON-NLS-1$
 
 	/**
 	 * Active code formatter ID.
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
index b7808858df5..ca03cbfd078 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
@@ -40,8 +40,9 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
 		Map defaultOptionsMap = DefaultCodeFormatterConstants.getDefaultSettings(); // code formatter defaults
 
 		// Compiler settings
-		defaultOptionsMap.put(CCorePreferenceConstants.TRANSLATION_TASK_TAGS, CCorePreferenceConstants.DEFAULT_TASK_TAG); 
-		defaultOptionsMap.put(CCorePreferenceConstants.TRANSLATION_TASK_PRIORITIES, CCorePreferenceConstants.DEFAULT_TASK_PRIORITY); 
+		defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_TAGS, CCorePreferenceConstants.DEFAULT_TASK_TAG); 
+		defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_PRIORITIES, CCorePreferenceConstants.DEFAULT_TASK_PRIORITY); 
+		defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_CASE_SENSITIVE, CCorePreferenceConstants.DEFAULT_TASK_CASE_SENSITIVE); 
 		defaultOptionsMap.put(CCorePreferenceConstants.CODE_FORMATTER, CCorePreferenceConstants.DEFAULT_CODE_FORMATTER); 
 		defaultOptionsMap.put(CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT, CCorePreferenceConstants.DEFAULT_INDEX_DB_CACHE_SIZE_PCT); 
 		defaultOptionsMap.put(CCorePreferenceConstants.MAX_INDEX_DB_CACHE_SIZE_MB, CCorePreferenceConstants.DEFAULT_MAX_INDEX_DB_CACHE_SIZE_MB); 
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index f5d394ee6a3..19326521b79 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -374,6 +374,9 @@ callHierarchy.name = Call Hierarchy
 typeHierarchy.name = Type Hierarchy
 cSearchPage.name = CSearchPage
 
+# Task tags
+todoTaskPrefName = Task Tags
+
 # dummy label (not displayed)
 Dummy.label = dummy
 
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index 6a5d2139dbc..b28182df5e9 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -673,6 +673,11 @@
             id="org.eclipse.cdt.ui.preferences.LanguageMappings"
             name="%CDTLanguagesProperty.name">
       
+