* Merge with HEAD
diff --git a/plugins/org.eclipse.dltk.ruby.core/plugin.xml b/plugins/org.eclipse.dltk.ruby.core/plugin.xml
index 8e60600..f869a84 100644
--- a/plugins/org.eclipse.dltk.ruby.core/plugin.xml
+++ b/plugins/org.eclipse.dltk.ruby.core/plugin.xml
@@ -107,4 +107,10 @@
            priority="1">
      </factory>
   </extension>
+  <extension
+        point="org.eclipse.core.runtime.preferences">
+     <initializer
+           class="org.eclipse.dltk.ruby.internal.core.RubyTodoPreferenceInitializer">
+     </initializer>
+  </extension>
 </plugin>
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/RubyTodoPreferenceInitializer.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/RubyTodoPreferenceInitializer.java
new file mode 100644
index 0000000..c61998f
--- /dev/null
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/RubyTodoPreferenceInitializer.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2008 xored software, Inc.  
+ *
+ * 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:
+ *     xored software, Inc. - initial API and Implementation (Andrei Sobolev)
+ *******************************************************************************/
+package org.eclipse.dltk.ruby.internal.core;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.dltk.compiler.task.TodoTaskPreferences;
+import org.eclipse.dltk.ruby.core.RubyPlugin;
+
+public class RubyTodoPreferenceInitializer extends
+		AbstractPreferenceInitializer {
+
+	public RubyTodoPreferenceInitializer() {
+	}
+
+	public void initializeDefaultPreferences() {
+		Preferences store = RubyPlugin.getDefault().getPluginPreferences();
+		TodoTaskPreferences.initializeDefaultValues(store);
+	}
+}
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/ProjectTypeComparator.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/ProjectTypeComparator.java
new file mode 100644
index 0000000..324728f
--- /dev/null
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/ProjectTypeComparator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008 xored software, Inc.
+ *
+ * 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:
+ *     xored software, Inc. - initial API and Implementation (Alex Panchenko)
+ *******************************************************************************/
+package org.eclipse.dltk.ruby.internal.core.codeassist;
+
+import java.util.Comparator;
+
+import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.IType;
+
+/**
+ * This {@link Comparator} is used to sort type proposals in the following
+ * order:
+ * <ol>
+ * <li>the specified module types should go first
+ * <li>other project types should go next
+ * <li>all other types should go last
+ * </ol>
+ */
+public class ProjectTypeComparator implements Comparator {
+
+	private final ISourceModule module;
+
+	/**
+	 * @param module
+	 */
+	public ProjectTypeComparator(ISourceModule module) {
+		this.module = module;
+	}
+
+	public int compare(Object o1, Object o2) {
+		final IType type1 = (IType) o1;
+		final IType type2 = (IType) o2;
+		if (type1.getParent() instanceof ISourceModule
+				&& type2.getParent() instanceof ISourceModule) {
+			final ISourceModule module1 = (ISourceModule) type1.getParent();
+			final ISourceModule module2 = (ISourceModule) type2.getParent();
+			if (module1.isReadOnly() != module2.isReadOnly()) {
+				return module1.isReadOnly() ? +1 : -1;
+			}
+			final boolean same1 = module.equals(module1);
+			if (same1 != module.equals(module2)) {
+				return same1 ? -1 : +1;
+			}
+		}
+		return type1.getElementName().compareTo(type2.getElementName());
+	}
+}
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubyCompletionEngine.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubyCompletionEngine.java
index f8e60f9..3a64c05 100644
--- a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubyCompletionEngine.java
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubyCompletionEngine.java
@@ -20,9 +20,7 @@
 import java.util.Locale;
 import java.util.Set;
 
-import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.dltk.ast.ASTNode;
 import org.eclipse.dltk.ast.Modifiers;
 import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
@@ -135,8 +133,7 @@
 	public RubyCompletionEngine() {
 		this.inferencer = new DLTKTypeInferenceEngine();
 		this.model = RubyMixinModel.getRawInstance();
-		this.parser = DLTKLanguageManager
-				.getSourceParser(RubyNature.NATURE_ID);
+		this.parser = DLTKLanguageManager.getSourceParser(RubyNature.NATURE_ID);
 	}
 
 	protected int getEndOfEmptyToken() {
@@ -213,17 +210,13 @@
 
 	public void complete(ISourceModule module, int position, int i) {
 		this.currentModule = module;
-		if (Job.getJobManager().find(ResourcesPlugin.FAMILY_AUTO_BUILD).length > 0) {
-			// FIXIT, make more correct awaiting for building
-			this.requestor.completionFailure(new DefaultProblem(null,
-					Messages.RubyCompletionEngine_pleaseWaitUntilBuildingIsReady, 0, null,
-					IStatus.WARNING, startPosition, endPosition, -1));
-			return;
-		}
 		if (!RubyPlugin.initialized) {
-			this.requestor.completionFailure(new DefaultProblem(null,
-					Messages.RubyCompletionEngine_pleaseWaitWhileDltkRubyBeingInitialized, 0,
-					null, IStatus.WARNING, startPosition, endPosition, -1));
+			this.requestor
+					.completionFailure(new DefaultProblem(
+							null,
+							Messages.RubyCompletionEngine_pleaseWaitWhileDltkRubyBeingInitialized,
+							0, null, IStatus.WARNING, startPosition,
+							endPosition, -1));
 			return;
 		}
 
@@ -594,10 +587,15 @@
 		reportSubElements(module, type, starting);
 	}
 
+	private int relevance;
+
 	private void completeConstant(org.eclipse.dltk.core.ISourceModule module,
 			ModuleDeclaration moduleDeclaration, String prefix, int position,
 			boolean topLevelOnly) {
 
+		relevance = 4242;
+		reportProjectTypes(module, prefix);
+
 		if (!topLevelOnly) {
 			IMixinElement[] modelStaticScopes = RubyTypeInferencingUtils
 					.getModelStaticScopes(model, moduleDeclaration, position);
@@ -610,8 +608,6 @@
 			}
 		}
 
-		int relevance = 4242;
-
 		// try {
 		if (prefix.length() > 0) {
 			String varkey = "Object" + MixinModel.SEPARATOR + prefix; //$NON-NLS-1$
@@ -636,16 +632,19 @@
 		// e.printStackTrace();
 		// }
 
-		HashSet names = new HashSet();
-		IType[] allTypes = RubyTypeInferencingUtils.getAllTypes(module, prefix);
-		for (int i = 0; i < allTypes.length; i++) {
-			String elementName = allTypes[i].getElementName();
-			if (names.contains(elementName))
-				continue;
-			names.add(elementName);
-			reportType(allTypes[i], relevance--);
-		}
+	}
 
+	private void reportProjectTypes(
+			final org.eclipse.dltk.core.ISourceModule module, String prefix) {
+		IType[] types = RubyTypeInferencingUtils.getAllTypes(module, prefix);
+		Arrays.sort(types, new ProjectTypeComparator(module));
+		final Set names = new HashSet();
+		for (int i = 0; i < types.length; i++) {
+			final String elementName = types[i].getElementName();
+			if (names.add(elementName)) {
+				reportType(types[i], relevance--);
+			}
+		}
 	}
 
 	private void completeConstant(org.eclipse.dltk.core.ISourceModule module,
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubySelectionEngine.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubySelectionEngine.java
index d4a7d5f..ca1484f 100644
--- a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubySelectionEngine.java
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/core/codeassist/RubySelectionEngine.java
@@ -5,12 +5,13 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
- 
+ * Contributors:
+ *     xored software, Inc. - initial API and Implementation (Andrei Sobolev)
+ *     xored software, Inc. - RubyDocumentation display improvements (Alex Panchenko <alex@xored.com>)
  *******************************************************************************/
 package org.eclipse.dltk.ruby.internal.core.codeassist;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -31,8 +32,10 @@
 import org.eclipse.dltk.compiler.env.ISourceModule;
 import org.eclipse.dltk.core.DLTKCore;
 import org.eclipse.dltk.core.IField;
+import org.eclipse.dltk.core.IMember;
 import org.eclipse.dltk.core.IMethod;
 import org.eclipse.dltk.core.IModelElement;
+import org.eclipse.dltk.core.IScriptProject;
 import org.eclipse.dltk.core.ISourceRange;
 import org.eclipse.dltk.core.IType;
 import org.eclipse.dltk.core.ModelException;
@@ -46,6 +49,7 @@
 import org.eclipse.dltk.ruby.ast.RubyAssignment;
 import org.eclipse.dltk.ruby.ast.RubyColonExpression;
 import org.eclipse.dltk.ruby.ast.RubySuperExpression;
+import org.eclipse.dltk.ruby.core.RubyPlugin;
 import org.eclipse.dltk.ruby.core.model.FakeField;
 import org.eclipse.dltk.ruby.core.utils.RubySyntaxUtils;
 import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinClass;
@@ -93,9 +97,9 @@
 	}
 
 	public RubySelectionEngine(/*
-								 * ISearchableEnvironment environment, Map
-								 * options, IDLTKLanguageToolkit toolkit
-								 */) {
+	 * ISearchableEnvironment environment, Map
+	 * options, IDLTKLanguageToolkit toolkit
+	 */) {
 		// super();
 		// setOptions(options);
 		// this.nameEnvironment = environment;
@@ -163,7 +167,8 @@
 				} else if (node instanceof MethodDeclaration) {
 					MethodDeclaration methodDeclaration = (MethodDeclaration) node;
 					selectionOnMethodDeclaration(parsedUnit, methodDeclaration);
-				} else if (node instanceof ConstantReference || node instanceof RubyColonExpression) {
+				} else if (node instanceof ConstantReference
+						|| node instanceof RubyColonExpression) {
 					selectTypes(modelModule, parsedUnit, node);
 				} else if (node instanceof VariableReference) {
 					selectionOnVariable(modelModule, parsedUnit,
@@ -180,41 +185,36 @@
 				}
 			}
 		} catch (IndexOutOfBoundsException e) { // work-around internal failure
-			if (DEBUG) {
-				System.out.println("Exception caught by RubySelectionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
+			RubyPlugin.log(e);
 		}
 
-		List resultElements = new ArrayList ();
-		
-		for (Iterator iterator = selectionElements.iterator(); iterator.hasNext();) {
-			IModelElement element = (IModelElement) iterator.next();
-			if (sourceUnit.getModelElement().getScriptProject().equals( 
-				element.getScriptProject()))
-				resultElements.add(element);
+		final List result = new ArrayList();
+		final IScriptProject sourceProject = sourceUnit.getModelElement()
+				.getScriptProject();
+		for (Iterator i = selectionElements.iterator(); i.hasNext();) {
+			final IModelElement element = (IModelElement) i.next();
+			if (sourceProject.equals(element.getScriptProject()))
+				result.add(element);
 		}
-		
-		return (IModelElement[]) resultElements
-				.toArray(new IModelElement[resultElements.size()]);
+		return (IModelElement[]) result
+				.toArray(new IModelElement[result.size()]);
 	}
-	
-	
 
 	private void selectOnSuper(org.eclipse.dltk.core.ISourceModule modelModule,
 			ModuleDeclaration parsedUnit, RubySuperExpression superExpr) {
-		RubyClassType selfClass = RubyTypeInferencingUtils.determineSelfClass(modelModule, parsedUnit, superExpr.sourceStart());
-		MethodDeclaration enclosingMethod = ASTUtils.getEnclosingMethod(wayToNode, superExpr, false);
+		RubyClassType selfClass = RubyTypeInferencingUtils.determineSelfClass(
+				modelModule, parsedUnit, superExpr.sourceStart());
+		MethodDeclaration enclosingMethod = ASTUtils.getEnclosingMethod(
+				wayToNode, superExpr, false);
 		if (enclosingMethod != null) {
 			String name = enclosingMethod.getName();
-			RubyMixinClass rubyClass = RubyMixinModel.getInstance().createRubyClass(selfClass);
+			RubyMixinClass rubyClass = RubyMixinModel.getInstance()
+					.createRubyClass(selfClass);
 			RubyMixinClass superclass = rubyClass.getSuperclass();
 			RubyMixinMethod method = superclass.getMethod(name);
 			if (method != null) {
 				IMethod[] sourceMethods = method.getSourceMethods();
-				for (int i = 0; i < sourceMethods.length; i++) {
-					this.selectionElements.add(sourceMethods[i]);
-				}
+				addArrayToCollection(sourceMethods, selectionElements);
 			}
 		}
 	}
@@ -228,18 +228,23 @@
 				new ExpressionTypeGoal(basicContext, node));
 		IGoal[] init = evaluator.init();
 		if (init == null || init.length == 0) {
-			 // should never be here
-			//System.err.println("Why did ColonExpressionEvaluator evaluated so fast?");
+			// should never be here
+			// System.err.println("Why did ColonExpressionEvaluator evaluated so
+			// fast?");
 		} else {
-			IEvaluatedType leftType = inferencer.evaluateType((AbstractTypeGoal) init[0], -1);
-			IGoal[] goals = evaluator.subGoalDone(init[0], leftType, GoalState.DONE);
-			if (goals== null || goals.length == 0) { // good, we have type-constant 
+			IEvaluatedType leftType = inferencer.evaluateType(
+					(AbstractTypeGoal) init[0], -1);
+			IGoal[] goals = evaluator.subGoalDone(init[0], leftType,
+					GoalState.DONE);
+			if (goals == null || goals.length == 0) { // good, we have
+				// type-constant
 				Object evaluatedType = evaluator.produceResult();
 				if (evaluatedType instanceof RubyClassType) {
 					RubyMixinClass mixinClass = RubyMixinModel.getInstance()
 							.createRubyClass((RubyClassType) evaluatedType);
 					if (mixinClass != null)
-						this.selectionElements.addAll(Arrays.asList(mixinClass.getSourceTypes()));
+						addArrayToCollection(mixinClass.getSourceTypes(),
+								selectionElements);
 				}
 			} else {
 				if (goals[0] instanceof NonTypeConstantTypeGoal) {
@@ -248,12 +253,13 @@
 			}
 		}
 	}
-	
+
 	/**
 	 * Uses goal info for selection on non-type goal
+	 * 
 	 * @param ngoal
 	 */
-	private void processNonTypeConstant (NonTypeConstantTypeGoal ngoal) {
+	private void processNonTypeConstant(NonTypeConstantTypeGoal ngoal) {
 		IMixinElement element = ngoal.getElement();
 		if (element != null) {
 			Object[] eObjects = element.getAllObjects();
@@ -283,11 +289,11 @@
 				RubyMixinClass mixinClass = RubyMixinModel.getInstance()
 						.createRubyClass((RubyClassType) evaluatedType);
 				if (mixinClass != null)
-					this.selectionElements.addAll(Arrays.asList(mixinClass.getSourceTypes()));
+					addArrayToCollection(mixinClass.getSourceTypes(),
+							selectionElements);
 			}
-		} else if (init[0] instanceof NonTypeConstantTypeGoal) { // it'a
-																	// non-type
-																	// constant
+		} else if (init[0] instanceof NonTypeConstantTypeGoal) {
+			// it'a non-type constant
 			processNonTypeConstant((NonTypeConstantTypeGoal) init[0]);
 		}
 	}
@@ -342,13 +348,13 @@
 	private void selectTypes(org.eclipse.dltk.core.ISourceModule modelModule,
 			ModuleDeclaration parsedUnit, ASTNode node) {
 		if (node instanceof ConstantReference) {
-			selectOnConstant(parsedUnit, (ConstantReference) node,
-					modelModule);
+			selectOnConstant(parsedUnit, (ConstantReference) node, modelModule);
 		} else if (node instanceof RubyColonExpression) {
-			selectOnColonExpression(parsedUnit, (RubyColonExpression) node, modelModule);
+			selectOnColonExpression(parsedUnit, (RubyColonExpression) node,
+					modelModule);
 		}
-		
-		if (this.selectionElements.isEmpty()) {
+
+		if (selectionElements.isEmpty()) {
 			TypeNameMatchRequestor requestor = new TypeNameMatchRequestor() {
 				public void acceptTypeNameMatch(TypeNameMatch match) {
 					selectionElements.add(match.getType());
@@ -376,9 +382,7 @@
 		if (name.startsWith("@")) { //$NON-NLS-1$
 			IField[] fields = RubyModelUtils.findFields(modelModule,
 					parsedUnit, name, e.sourceStart());
-			for (int i = 0; i < fields.length; i++) {
-				selectionElements.add(fields[i]);
-			}
+			addArrayToCollection(fields, selectionElements);
 		} else { // local vars (legacy, saved for speed reasons: we dont need
 			// to use mixin model for local vars)
 			ASTNode parentScope = null;
@@ -403,10 +407,9 @@
 				RubyAssignment[] assignments = RubyTypeInferencingUtils
 						.findLocalVariableAssignments(parentScope, e, name);
 				if (assignments.length > 0) {
-					RubyAssignment assignment = assignments[0];
-					selectionElements.add(createLocalVariable(name, assignment
-							.getLeft().sourceStart(), assignment.getLeft()
-							.sourceEnd()));
+					final ASTNode left = assignments[0].getLeft();
+					selectionElements.add(createLocalVariable(name, left
+							.sourceStart(), left.sourceEnd()));
 				} else {
 					selectionElements.add(createLocalVariable(name, e
 							.sourceStart(), e.sourceEnd()));
@@ -476,77 +479,76 @@
 	private void selectOnMethod(
 			org.eclipse.dltk.core.ISourceModule modelModule,
 			ModuleDeclaration parsedUnit, CallExpression parentCall) {
-		String methodName = ((CallExpression) parentCall).getName();
+		String methodName = parentCall.getName();
 		ASTNode receiver = parentCall.getReceiver();
 
-		IMethod[] availableMethods = null;
-		IMethod[] availableMethods2 = null;
+		final List availableMethods = new ArrayList();
 
 		if (receiver == null) {
 			RubyClassType type = RubyTypeInferencingUtils.determineSelfClass(
 					modelModule, parsedUnit, parentCall.sourceStart());
-			availableMethods = RubyModelUtils.searchClassMethods(modelModule,
+			IMethod[] m = RubyModelUtils.searchClassMethods(modelModule,
 					parsedUnit, type, methodName);
+			addArrayToCollection(m, availableMethods);
 		} else {
 			ExpressionTypeGoal goal = new ExpressionTypeGoal(new BasicContext(
 					modelModule, parsedUnit), receiver);
 			IEvaluatedType type = inferencer.evaluateType(goal, 5000);
-			availableMethods = RubyModelUtils.searchClassMethods(modelModule,
+			IMethod[] m = RubyModelUtils.searchClassMethods(modelModule,
 					parsedUnit, type, methodName);
+			addArrayToCollection(m, availableMethods);
 			if (receiver instanceof VariableReference) {
-				availableMethods2 = RubyModelUtils.getSingletonMethods(
-						(VariableReference) receiver, parsedUnit, modelModule,
-						methodName);
+				IMethod[] availableMethods2 = RubyModelUtils
+						.getSingletonMethods((VariableReference) receiver,
+								parsedUnit, modelModule, methodName);
+				addArrayToCollection(availableMethods2, availableMethods);
 			}
 		}
 
-		if (availableMethods2 != null) {
-			IMethod[] newm = new IMethod[((availableMethods != null) ? availableMethods.length
-					: 0)
-					+ availableMethods2.length];
-			int next = 0;
-			if (availableMethods != null) {
-				System.arraycopy(availableMethods, 0, newm, 0,
-						availableMethods.length);
-				next = availableMethods.length;
-			}
-			System.arraycopy(availableMethods2, 0, newm, next,
-					availableMethods2.length);
-			availableMethods = newm;
-		}
-
-		if (availableMethods == null || availableMethods.length == 0) {
-			final Collection methods = new ArrayList();
+		if (availableMethods.isEmpty()) {
 			SearchRequestor requestor = new SearchRequestor() {
 
 				public void acceptSearchMatch(SearchMatch match)
 						throws CoreException {
-					IModelElement modelElement = (IModelElement) match.getElement();
-					org.eclipse.dltk.core.ISourceModule sm = (org.eclipse.dltk.core.ISourceModule) modelElement.getAncestor(IModelElement.SOURCE_MODULE);
-					IModelElement elementAt = sm.getElementAt(match.getOffset());
-					methods.add(elementAt);
+					IModelElement modelElement = (IModelElement) match
+							.getElement();
+					org.eclipse.dltk.core.ISourceModule sm = (org.eclipse.dltk.core.ISourceModule) modelElement
+							.getAncestor(IModelElement.SOURCE_MODULE);
+					IModelElement elementAt = sm
+							.getElementAt(match.getOffset());
+					availableMethods.add(elementAt);
 				}
 
 			};
 			ScriptModelUtil.searchMethodDeclarations(modelModule
 					.getScriptProject(), methodName, requestor);
-			availableMethods = (IMethod[]) methods.toArray(new IMethod[methods
-					.size()]);
-//			if (availableMethods.length > 0)
-//				System.out
-//						.println("RubySelectionEngine.selectOnMethod() used global search");
+			// if (availableMethods.length > 0)
+			// System.out
+			// .println("RubySelectionEngine.selectOnMethod() used global
+			// search");
 		}
 
-		if (availableMethods != null) {
-			int count = 0;
-			for (int i = 0; i < availableMethods.length; i++) {
-				if (availableMethods[i].getElementName().equals(methodName)) {
-					selectionElements.add(availableMethods[i]);
-					++count;
+		if (!availableMethods.isEmpty()) {
+			for (int i = 0, size = availableMethods.size(); i < size; ++i) {
+				final IMethod m = (IMethod) availableMethods.get(i);
+				if (methodName.equals(methodName)) {
+					selectionElements.add(m);
 				}
 			}
 		}
 
 	}
 
+	/**
+	 * @param src
+	 * @param dest
+	 */
+	private static void addArrayToCollection(IMember[] src, Collection dest) {
+		if (src != null) {
+			for (int i = 0, size = src.length; i < size; ++i) {
+				dest.add(src[i]);
+			}
+		}
+	}
+
 }
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/JRubySourceParser.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/JRubySourceParser.java
index 16a23e9..aef6575 100644
--- a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/JRubySourceParser.java
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/JRubySourceParser.java
@@ -29,8 +29,10 @@
 import org.eclipse.dltk.ast.parser.AbstractSourceParser;
 import org.eclipse.dltk.ast.references.ConstantReference;
 import org.eclipse.dltk.ast.statements.Block;
+import org.eclipse.dltk.compiler.problem.AbstractProblemReporter;
 import org.eclipse.dltk.compiler.problem.IProblem;
 import org.eclipse.dltk.compiler.problem.IProblemReporter;
+import org.eclipse.dltk.compiler.problem.ProblemReporterProxy;
 import org.eclipse.dltk.core.DLTKCore;
 import org.eclipse.dltk.ruby.ast.RubyClassDeclaration;
 import org.eclipse.dltk.ruby.ast.RubyModuleDeclaration;
@@ -273,32 +275,19 @@
     return parserResult;
   }
 
-	private class ProxyProblemReporter implements IProblemReporter {
-
-		private final IProblemReporter original;
+	private class ProxyProblemReporter extends ProblemReporterProxy {
 
 		public ProxyProblemReporter(IProblemReporter original) {
-			super();
-			this.original = original;
+			super(original);
 		}
 
 		public IMarker reportProblem(IProblem problem) throws CoreException {
-			IMarker m = null;
-			if (original != null)
-				m = original.reportProblem(problem);
 			if (problem.isError()) {
 				errorState[0] = true;
 			}
-			return m;
+			return super.reportProblem(problem);
 		}
 
-		public void clearMarkers() {
-			this.original.clearMarkers();
-		}
-
-		public boolean isMarkersCleaned() {
-			return original.isMarkersCleaned();
-		}
 	}
 	
 	public JRubySourceParser() {
@@ -514,7 +503,7 @@
                     content2 = fixBrokenCommasUnsafe(content2);
                     content2 = fixBrokenHashesUnsafe(content2);
 
-                    node2 = parser.parse("", new StringReader(content2), new IProblemReporter() { //$NON-NLS-1$
+                    node2 = parser.parse("", new StringReader(content2), new AbstractProblemReporter() { //$NON-NLS-1$
 
                       public IMarker reportProblem(IProblem problem) {
                         if (DLTKCore.DEBUG) {
@@ -530,13 +519,6 @@
                         return null;
                       }
 
-              		  public void clearMarkers() {
-            		  }
-
-              		  public boolean isMarkersCleaned() {
-              			  return true;
-              		  }
-
                     });
                     if (node2 != null)
                       node = node2;
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/RubySourceElementParser.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/RubySourceElementParser.java
index 4e0d695..6ab1655 100644
--- a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/RubySourceElementParser.java
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/RubySourceElementParser.java
@@ -10,8 +10,13 @@
 package org.eclipse.dltk.ruby.internal.parser;
 
 import org.eclipse.dltk.compiler.SourceElementRequestVisitor;
+import org.eclipse.dltk.compiler.task.ITaskReporter;
+import org.eclipse.dltk.compiler.task.TodoTaskPreferences;
+import org.eclipse.dltk.compiler.task.TodoTaskSimpleParser;
 import org.eclipse.dltk.core.AbstractSourceElementParser;
+import org.eclipse.dltk.core.ISourceModuleInfoCache.ISourceModuleInfo;
 import org.eclipse.dltk.ruby.core.RubyNature;
+import org.eclipse.dltk.ruby.core.RubyPlugin;
 import org.eclipse.dltk.ruby.internal.parser.visitors.RubySourceElementRequestor;
 
 public class RubySourceElementParser extends AbstractSourceElementParser {
@@ -29,4 +34,30 @@
 	protected String getNatureId() {
 		return RubyNature.NATURE_ID;
 	}
+
+	public void parseSourceModule(char[] contents, ISourceModuleInfo astCache,
+			char[] filename) {
+		super.parseSourceModule(contents, astCache, filename);
+		if (getProblemReporter() != null) {
+			final ITaskReporter taskReporter = (ITaskReporter) getProblemReporter()
+					.getAdapter(ITaskReporter.class);
+			if (taskReporter != null) {
+				taskReporter.clearTasks();
+				parseTasks(taskReporter, contents);
+			}
+		}
+	}
+
+	protected void parseTasks(ITaskReporter taskReporter, char[] content) {
+		final TodoTaskPreferences preferences = new TodoTaskPreferences(
+				RubyPlugin.getDefault().getPluginPreferences());
+		if (preferences.isEnabled()) {
+			final TodoTaskSimpleParser taskParser = new TodoTaskSimpleParser(
+					taskReporter, preferences);
+			if (taskParser.isValid()) {
+				taskParser.parse(content);
+			}
+		}
+	}
+
 }
diff --git a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/mixin/RubyMixinMethod.java b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/mixin/RubyMixinMethod.java
index f6d7e10..a5e1acc 100644
--- a/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/mixin/RubyMixinMethod.java
+++ b/plugins/org.eclipse.dltk.ruby.core/src/org/eclipse/dltk/ruby/internal/parser/mixin/RubyMixinMethod.java
@@ -5,7 +5,9 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
- 
+ * Contributors:
+ *     xored software, Inc. - initial API and Implementation (Andrei Sobolev)
+ *     xored software, Inc. - RubyDocumentation display improvements (Alex Panchenko <alex@xored.com>)
  *******************************************************************************/
 package org.eclipse.dltk.ruby.internal.parser.mixin;
 
@@ -71,21 +73,24 @@
 	 */
 	public IMethod[] getSourceMethods() {
 		if (this.sourceMethods != null)
-			return sourceMethods;		
+			return sourceMethods;
 		return RubyMixinMethod.getSourceMethods(model, key);
 	}
-	
-	protected static IMethod[] getSourceMethods (RubyMixinModel model, String key) {
-		List result = new ArrayList();
-		IMixinElement mixinElement = model.getRawModel().get(key);
-		Object[] allObjects = mixinElement.getAllObjects();
-		for (int i = 0; i < allObjects.length; i++) {
-			RubyMixinElementInfo info = (RubyMixinElementInfo) allObjects[i];
-			if (info.getKind() == RubyMixinElementInfo.K_METHOD) {
-				result.add(info.getObject());
+
+	protected static IMethod[] getSourceMethods(RubyMixinModel model, String key) {
+		final IMixinElement mixinElement = model.getRawModel().get(key);
+		if (mixinElement != null) {
+			final Object[] allObjects = mixinElement.getAllObjects();
+			final List result = new ArrayList();
+			for (int i = 0; i < allObjects.length; i++) {
+				RubyMixinElementInfo info = (RubyMixinElementInfo) allObjects[i];
+				if (info.getKind() == RubyMixinElementInfo.K_METHOD) {
+					result.add(info.getObject());
+				}
 			}
+			return (IMethod[]) result.toArray(new IMethod[result.size()]);
 		}
-		return (IMethod[]) result.toArray(new IMethod[result.size()]);
+		return new IMethod[0];
 	}
 
 	public RubyMixinVariable[] getVariables() {