Code cleanup. Added more tests.
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
index c12d6cf..1a4e2cf 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
@@ -51,13 +51,13 @@
           }
         }
         if (segment.contains(NESTED_ELEMENT_SEPARATOR)) {
-          List<Message> matchingNestedElements = matchingNestedElements(message, segment);
+          List<Message> nestedMessages = matchingNestedMessages(message, segment);
           if (qualifiedName.wasLastListElementRetrieved()) {
-            for (Message m : matchingNestedElements) {
+            for (Message m : nestedMessages) {
               matches.add(modelObjects.uriOf(m));
             }
           } else {
-            for (Message m : matchingNestedElements) {
+            for (Message m : nestedMessages) {
               matches.addAll(matchingProtobufElementLocations(m, qualifiedName.notRetrievedYet()));
             }
           }
@@ -67,23 +67,23 @@
     return unmodifiableList(matches);
   }
 
-  private List<Message> matchingNestedElements(Message message, String qualifiedName) {
+  private List<Message> matchingNestedMessages(Message root, String qualifiedName) {
     List<Message> matches = newArrayList();
-    String messageName = message.getName();
+    String messageName = root.getName();
     if (qualifiedName.startsWith(messageName)) {
       String rest = qualifiedName.substring(messageName.length());
       if (rest.isEmpty()) {
-        matches.add(message);
+        matches.add(root);
       }
       else {
         if (rest.startsWith(NESTED_ELEMENT_SEPARATOR)) {
           rest = rest.substring(1);
         }
-        for (EObject o : message.eContents()) {
+        for (EObject o : root.eContents()) {
           if (!isSupported(o)) {
             continue;
           }
-          matches.addAll(matchingNestedElements((Message) o, rest));
+          matches.addAll(matchingNestedMessages((Message) o, rest));
         }
       }
     }
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator.java
index b20ca67..fc252c3 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator.java
@@ -8,12 +8,13 @@
  */
 package com.google.eclipse.protobuf.cdt.util;
 
+import static com.google.common.collect.Lists.newArrayList;
 import static java.util.Collections.*;
 
 import java.util.List;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.*;
+import com.google.common.collect.AbstractIterator;
 
 /**
  * {@code Iterator} for {@code List}s. This implementation keeps track of the index of the current element to be able
@@ -27,11 +28,11 @@
  */
 public class ExtendedListIterator<T> extends AbstractIterator<T> implements ExtendedIterator<T> {
   private static final ExtendedIterator<Object> EMPTY = newIterator(emptyList());
+  private static final int NOT_STARTED = -1;
 
   private final List<T> list;
-  private final int listSize;
 
-  private int index = -1;
+  private int index = NOT_STARTED;
 
   /**
    * Creates a new <code>{@link ExtendedListIterator}</code>.
@@ -39,26 +40,30 @@
    * @return the created {@code ListIterator}.
    */
   public static <T> ExtendedIterator<T> newIterator(T...elements) {
-    return new ExtendedListIterator<T>(Lists.newArrayList(elements));
+    return new ExtendedListIterator<T>(newArrayList(elements));
   }
 
   /**
    * Creates a new <code>{@link ExtendedListIterator}</code>.
    * @param list the {@code List} to iterate.
    * @return the created {@code ListIterator}.
+   * @throws NullPointerException if the given {@code List} is {@code null}.
    */
   public static <T> ExtendedIterator<T> newIterator(List<T> list) {
+    if (list == null) {
+      throw new NullPointerException("The list to iterate should not be null");
+    }
     return new ExtendedListIterator<T>(list);
   }
 
   @VisibleForTesting ExtendedListIterator(List<T> list) {
     this.list = list;
-    listSize = list.size();
   }
 
   /** {@inheritDoc} */
-  @Override @SuppressWarnings("unchecked")
-  public ExtendedIterator<T> notRetrievedYet() {
+  @SuppressWarnings("unchecked")
+  @Override public ExtendedIterator<T> notRetrievedYet() {
+    int listSize = list.size();
     if (listSize == 0) {
       return (ExtendedIterator<T>) EMPTY;
     }
@@ -68,6 +73,10 @@
 
   /** {@inheritDoc} */
   @Override public boolean wasLastListElementRetrieved() {
+    if (index == NOT_STARTED) {
+      return false;
+    }
+    int listSize = list.size();
     return listSize > 0 && index == listSize - 1;
   }
 
@@ -77,6 +86,7 @@
   }
 
   @Override protected T computeNext() {
+    int listSize = list.size();
     if (index + 1 < listSize && listSize > 0) {
       return list.get(++index);
     }
@@ -90,5 +100,4 @@
   @VisibleForTesting List<T> contents() {
     return unmodifiableList(list);
   }
-
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
index 2e57867..bb407d3 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/XtextRule.java
@@ -16,12 +16,12 @@
 import static org.eclipse.xtext.util.CancelIndicator.NullImpl;
 import static org.eclipse.xtext.util.Strings.isEmpty;
 
-import com.google.eclipse.protobuf.protobuf.Protobuf;
-import com.google.inject.*;
+import java.io.*;
+import java.util.List;
 
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.ISetup;
+import org.eclipse.xtext.*;
 import org.eclipse.xtext.linking.lazy.LazyLinkingResource;
 import org.eclipse.xtext.nodemodel.*;
 import org.eclipse.xtext.parser.IParseResult;
@@ -30,7 +30,8 @@
 import org.junit.rules.MethodRule;
 import org.junit.runners.model.*;
 
-import java.io.*;
+import com.google.eclipse.protobuf.protobuf.Protobuf;
+import com.google.inject.*;
 
 /**
  * Rule that performs configuration of a standalone Xtext environment.
@@ -152,4 +153,9 @@
   public ILeafNode find(String text) {
     return finder.find(text);
   }
+
+  public <T extends EObject> T findFirst(Class<T> type) {
+    List<T> contents = EcoreUtil2.getAllContentsOfType(root, type);
+    return (contents.isEmpty()) ? null : contents.get(0);
+  }
 }
diff --git a/com.google.eclipse.protobuf.ui/icons/field-opt.gif b/com.google.eclipse.protobuf.ui/icons/optional.gif
similarity index 100%
rename from com.google.eclipse.protobuf.ui/icons/field-opt.gif
rename to com.google.eclipse.protobuf.ui/icons/optional.gif
Binary files differ
diff --git a/com.google.eclipse.protobuf.ui/icons/field-rep.gif b/com.google.eclipse.protobuf.ui/icons/repeated.gif
similarity index 100%
rename from com.google.eclipse.protobuf.ui/icons/field-rep.gif
rename to com.google.eclipse.protobuf.ui/icons/repeated.gif
Binary files differ
diff --git a/com.google.eclipse.protobuf.ui/icons/field-req.gif b/com.google.eclipse.protobuf.ui/icons/required.gif
similarity index 100%
rename from com.google.eclipse.protobuf.ui/icons/field-req.gif
rename to com.google.eclipse.protobuf.ui/icons/required.gif
Binary files differ
diff --git a/com.google.eclipse.protobuf.ui/icons/extend.gif b/com.google.eclipse.protobuf.ui/icons/typeextension.gif
similarity index 100%
rename from com.google.eclipse.protobuf.ui/icons/extend.gif
rename to com.google.eclipse.protobuf.ui/icons/typeextension.gif
Binary files differ
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
index 2415f8e..29472e0 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
@@ -10,7 +10,9 @@
 
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.eclipse.protobuf.grammar.CommonKeyword.*;
+import static com.google.eclipse.protobuf.grammar.CommonKeyword.SYNTAX;
 import static com.google.eclipse.protobuf.protobuf.Modifier.*;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
 import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.*;
 import static com.google.eclipse.protobuf.util.CommonWords.space;
 import static java.lang.String.valueOf;
@@ -40,6 +42,7 @@
 import com.google.eclipse.protobuf.ui.labeling.Images;
 import com.google.inject.Inject;
 
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  *
@@ -66,7 +69,7 @@
   @Override public void complete_Syntax(EObject model, RuleCall ruleCall, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
     String proposal = SYNTAX + space() + EQUAL_PROTO2_IN_QUOTES;
-    proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor);
+    proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(SYNTAX)), context, acceptor);
   }
 
   @Override public void completeComplexTypeLink_Target(EObject model, Assignment assignment,
@@ -528,7 +531,7 @@
   }
 
   private Image imageForOption() {
-    return imageHelper.getImage(images.imageFor(Option.class));
+    return imageHelper.getImage(images.imageFor(OPTION));
   }
 
   private void proposeAndAccept(IEObjectDescription d, Image image, ContentAssistContext context,
@@ -625,7 +628,7 @@
   }
 
   private void proposeAndAccept(Enum enumType, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-    Image image = imageHelper.getImage(images.imageFor(Literal.class));
+    Image image = imageHelper.getImage(images.imageFor(LITERAL));
     for (Literal literal : getAllContentsOfType(enumType, Literal.class)) {
       proposeAndAccept(literal.getName(), image, context, acceptor);
     }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
index 903e0d3..22204a6 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
@@ -8,18 +8,17 @@
  */
 package com.google.eclipse.protobuf.ui.labeling;
 
-import static com.google.common.collect.ImmutableList.of;
-import static com.google.common.collect.Maps.newHashMap;
+import static com.google.common.collect.Sets.newHashSet;
 import static com.google.eclipse.protobuf.protobuf.Modifier.*;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
 
-import java.util.Map;
+import java.util.Set;
 
+import org.eclipse.emf.ecore.*;
 import org.eclipse.xtext.Keyword;
 
-import com.google.common.collect.ImmutableList;
+import com.google.eclipse.protobuf.grammar.CommonKeyword;
 import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.inject.Singleton;
 
 /**
@@ -28,84 +27,80 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 @Singleton public class Images {
-  private static final String GIF_EXTENSION = ".gif";
+  private static final String IMAGE_FILE_NAME_FORMAT = "%s.gif";
   private static final String DEFAULT_IMAGE = "empty.gif";
 
-  private static final Map<Modifier, String> IMAGES_BY_MODIFIER = newHashMap();
+  private static final Set<String> IMAGES = newHashSet();
   static {
-    IMAGES_BY_MODIFIER.put(OPTIONAL, "field-opt.gif");
-    IMAGES_BY_MODIFIER.put(REPEATED, "field-rep.gif");
-    IMAGES_BY_MODIFIER.put(REQUIRED, "field-req.gif");
+    addImages(OPTIONAL, REPEATED, REQUIRED);
+    addImages(ENUM, TYPE_EXTENSION, EXTENSIONS, GROUP, IMPORT, LITERAL, MESSAGE, OPTION, PACKAGE, RPC, SERVICE, SYNTAX);
+    addImages("imports", "options");
   }
 
-  private static final Map<Class<?>, String> IMAGES_BY_TYPE = newHashMap();
-  static {
-    IMAGES_BY_TYPE.put(Enum.class, "enum.gif");
-    IMAGES_BY_TYPE.put(TypeExtension.class, "extend.gif");
-    IMAGES_BY_TYPE.put(Extensions.class, "extensions.gif");
-    IMAGES_BY_TYPE.put(Group.class, "group.gif");
-    IMAGES_BY_TYPE.put(Import.class, "import.gif");
-    IMAGES_BY_TYPE.put(Literal.class, "literal.gif");
-    IMAGES_BY_TYPE.put(Message.class, "message.gif");
-    IMAGES_BY_TYPE.put(Option.class, "option.gif");
-    IMAGES_BY_TYPE.put(Package.class, "package.gif");
-    IMAGES_BY_TYPE.put(Rpc.class, "rpc.gif");
-    IMAGES_BY_TYPE.put(Service.class, "service.gif");
-    IMAGES_BY_TYPE.put(Syntax.class, "syntax.gif");
+  private static void addImages(Modifier...modifiers) {
+    for (Modifier m : modifiers) {
+      addImage(imageNameFrom(m));
+    }
   }
 
-  private static final ImmutableList<String> STANDALONE_IMAGES = of("extensions.gif", "imports.gif", "options.gif");
+  private static void addImages(EClass...eClasses) {
+    for (EClass c : eClasses) {
+      addImage(imageNameFrom(c));
+    }
+  }
+
+  private static void addImages(String...imageNames) {
+    for (String s : imageNames) {
+      addImage(s);
+    }
+  }
+
+  private static void addImage(String imageName) {
+    IMAGES.add(imageFileName(imageName));
+  }
 
   public String imageFor(Object o) {
+    String imageName = null;
     if (o instanceof Keyword) {
-      Keyword k = (Keyword) o;
-      return imageFor(k);
+      Keyword keyword = (Keyword) o;
+      imageName = keyword.getValue().toLowerCase();
+    } else if (o instanceof CommonKeyword) {
+      CommonKeyword keyword = (CommonKeyword) o;
+      imageName = keyword.toString();
+    } else if (o instanceof String) {
+      imageName = (String) o;
+    } else if (o instanceof MessageField) {
+      MessageField field = (MessageField) o;
+      Modifier modifier = field.getModifier();
+      imageName = imageNameFrom(modifier);
+    } else if (o instanceof Option) {
+      imageName = imageNameFrom(OPTION);
+    } else if (o instanceof Import) {
+      imageName = imageNameFrom(IMPORT);
+    } else if (o instanceof EClass) {
+      EClass eClass = (EClass) o;
+      imageName = imageNameFrom(eClass);
+    } else if (o instanceof EObject) {
+      EObject modelObject = (EObject) o;
+      imageName = imageNameFrom(modelObject.eClass());
     }
-    if (o instanceof MessageField) {
-      MessageField f = (MessageField) o;
-      return imageFor(f.getModifier());
+    String imageFileName = null;
+    if (imageName != null) {
+      imageFileName = imageFileName(imageName);
     }
-    if (o instanceof String) {
-      return o + GIF_EXTENSION;
-    }
-    if (o instanceof Option) {
-      return imageFor(Option.class);
-    }
-    return imageFor(o.getClass());
+    return (IMAGES.contains(imageFileName)) ? imageFileName : defaultImage();
   }
 
-  public String imageFor(Class<?> type) {
-    String image = IMAGES_BY_TYPE.get(type);
-    if (image != null) {
-      return image;
-    }
-    Class<?>[] interfaces = type.getInterfaces();
-    if (interfaces == null || interfaces.length == 0) {
-      return DEFAULT_IMAGE;
-    }
-    return imageFor(interfaces[0]);
+  private static String imageNameFrom(Modifier modifier) {
+    return modifier.getName().toLowerCase();
   }
 
-  private String imageFor(Keyword keyword) {
-    String value = keyword.getValue();
-    Modifier m = Modifier.getByName(value);
-    String image = IMAGES_BY_MODIFIER.get(m);
-    if (image != null) {
-      return image;
-    }
-    String imageName = value + GIF_EXTENSION;
-    if (IMAGES_BY_TYPE.containsValue(imageName) || STANDALONE_IMAGES.contains(imageName)) {
-      return imageName;
-    }
-    return DEFAULT_IMAGE;
+  private static String imageNameFrom(EClass eClass) {
+    return eClass.getName().toLowerCase();
   }
 
-  private String imageFor(Modifier modifier) {
-    String image = IMAGES_BY_MODIFIER.get(modifier);
-    if (image != null) {
-      return image;
-    }
-    return "field.gif";
+  private static String imageFileName(String imageName) {
+    return String.format(IMAGE_FILE_NAME_FORMAT, imageName);
   }
 
   public String defaultImage() {