In progress: [Issue 164] Validate that the default value of a field
matches the type of such field.

Added validation for default values of numeric fields.
diff --git a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
index c4df5f0..1817545 100644
--- a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
+++ b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
@@ -20,5 +20,5 @@
 command.description.1 = Insert semicolon.
 command.name.1 = Insert semicolon
 command.tooltip.1 = Insert semicolon
-protoc.marker.name = Protocol Buffer Compiler
+protoc.marker.name = Protocol Buffer Problem (Compiler)
 editor.marker.name = Protocol Buffer Problem
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtocMarkerFactory.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtocMarkerFactory.java
index 7403a06..7470db9 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtocMarkerFactory.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtocMarkerFactory.java
@@ -8,9 +8,9 @@
  */
 package com.google.eclipse.protobuf.ui.builder.protoc;
 
+import static com.google.eclipse.protobuf.ui.validation.ProtobufResourceUIValidatorExtension.EDITOR_CHECK;
 import static org.eclipse.core.resources.IMarker.*;
 import static org.eclipse.core.resources.IResource.DEPTH_INFINITE;
-import static org.eclipse.xtext.ui.MarkerTypes.FAST_VALIDATION;
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.CoreException;
@@ -30,7 +30,7 @@
   ProtocMarkerFactory(IFile file) throws CoreException {
     this.file = file;
     file.deleteMarkers(PROTOC_CHECK, true, DEPTH_INFINITE);
-    markers = file.findMarkers(FAST_VALIDATION, true, DEPTH_INFINITE);
+    markers = file.findMarkers(EDITOR_CHECK, true, DEPTH_INFINITE);
   }
 
   void createErrorIfNecessary(String fileName, String message, int lineNumber) throws CoreException {
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 a0c3d35..b8109f4 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
@@ -201,7 +201,7 @@
 
   private boolean isNanProposalValid(ContentAssistContext context) {
     MessageField field = fieldFrom(context);
-    return field != null && messageFields.mayBeNan(field);
+    return field != null && messageFields.isFloatingPointNumber(field);
   }
 
   private MessageField fieldFrom(ContentAssistContext context) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufResourceUIValidatorExtension.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufResourceUIValidatorExtension.java
index 18c5e11..f91ffed 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufResourceUIValidatorExtension.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufResourceUIValidatorExtension.java
@@ -10,8 +10,7 @@
 
 import static org.eclipse.core.resources.IResource.DEPTH_ZERO;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.inject.Inject;
+import java.util.List;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.*;
@@ -19,17 +18,18 @@
 import org.eclipse.xtext.ui.validation.DefaultResourceUIValidatorExtension;
 import org.eclipse.xtext.validation.*;
 
-import java.util.List;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.Inject;
 
 /**
  * Creates/deletes markers of type "Protocol Buffer Problem" instead of the default "Xtext Check."
- * 
+ *
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class ProtobufResourceUIValidatorExtension extends DefaultResourceUIValidatorExtension {
 
-  static final String EDITOR_CHECK = "com.google.eclipse.protobuf.ui.editorMarker";
-  
+  public static final String EDITOR_CHECK = "com.google.eclipse.protobuf.ui.editorMarker";
+
   @VisibleForTesting
   @Inject MarkerCreator markerCreator;
 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
index 921af4f..353ea83 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
@@ -19,9 +19,13 @@
   // looking for. The code was too complicated and if the grammar changed for some reason, we had to change our
   // implementation anyway.
 
-  BOOL("bool"), TRUE("true"), FALSE("false"), BYTES("bytes"), OPENING_BRACKET("["), CLOSING_BRACKET("]"),
-      OPENING_CURLY_BRACKET("{"), CLOSING_CURLY_BRACKET("}"), DEFAULT("default"), EQUAL("="), SEMICOLON(";"),
-      STRING("string"), SYNTAX("syntax"), NAN("nan"), FLOAT("float"), DOUBLE("double");
+
+  BOOL("bool"), BYTES("bytes"), CLOSING_BRACKET("]"), CLOSING_CURLY_BRACKET("}"), DEFAULT("default"), DOUBLE("double"),
+  EQUAL("="), FALSE("false"), FIXED32("fixed32"), FIXED64("fixed64"), FLOAT("float"), INT32("int32"), INT64("int64"),
+  NAN("nan"), OPENING_BRACKET("["), OPENING_CURLY_BRACKET("{"), SEMICOLON(";"), SFIXED32("sfixed32"),
+  SFIXED64("sfixed64"), STRING("string"), SYNTAX("syntax"), TRUE("true"), SINT32("sint32"), SINT64("sint64"),
+  UINT32("unit32"), UINT64("uint64");
+
 
   private final String value;
 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java
index 1970a4a..ffcd151 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java
@@ -13,7 +13,7 @@
 
 import com.google.eclipse.protobuf.grammar.CommonKeyword;
 import com.google.eclipse.protobuf.protobuf.*;
-import com.google.inject.*;
+import com.google.inject.Singleton;
 
 /**
  * Utility methods related to <code>{@link MessageField}</code>s.
@@ -56,13 +56,22 @@
   }
 
   /**
-   * Indicates whether the given field can accept "nan" as its default value.
+   * Indicates whether the given field is of type {@code float} or {@code double}.
    * @param field the given field.
-   * @return {@code true} if the given field can accept "nan" as its default value, {@code false} otherwise.
+   * @return {@code true} if the given field is a floating point number, {@code false} otherwise.
    */
-  public boolean mayBeNan(MessageField field) {
-    String typeName = typeNameOf(field);
-    return FLOAT.hasValue(typeName) || DOUBLE.hasValue(typeName);
+  public boolean isFloatingPointNumber(MessageField field) {
+    return isScalarType(field, FLOAT, DOUBLE);
+  }
+
+  /**
+   * Indicates whether the given field is of type {@code fixed32}, {@code fixed64}, {@code int32}, {@code int64},
+   * {@code sfixed32}, {@code sfixed64}, {@code sint32}, {@code sint64}, {@code uint32} or {@code uint64}.
+   * @param field the given field.
+   * @return {@code true} if the given field is an integer, {@code false} otherwise.
+   */
+  public boolean isInteger(MessageField field) {
+    return isScalarType(field, FIXED32, FIXED64, INT32, INT64, SFIXED32, SFIXED64, SINT32, SINT64, UINT32, UINT64);
   }
 
   /**
@@ -74,8 +83,24 @@
     return isScalarType(field, STRING);
   }
 
-  private boolean isScalarType(MessageField field, CommonKeyword typeKeyword) {
-    return typeKeyword.hasValue(typeNameOf(field));
+  /**
+   * Indicates whether the given field is of type {@code fixed32}, {@code fixed64}, {@code uint32} or {@code uint64}.
+   * @param field the given field.
+   * @return {@code true} if the given field is an unsigned integer, {@code false} otherwise.
+   */
+  public boolean isUnsignedInteger(MessageField field) {
+    return isScalarType(field, FIXED32, FIXED64, UINT32, UINT64);
+  }
+
+  private boolean isScalarType(MessageField field, CommonKeyword...scalarNames) {
+    TypeLink link = field.getType();
+    if (link instanceof ScalarTypeLink) {
+      String typeName = ((ScalarTypeLink) link).getTarget().getName();
+      for (CommonKeyword scalarName : scalarNames) {
+        if (scalarName.hasValue(typeName)) return true;
+      }
+    }
+    return false;
   }
 
   /**
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/DataTypeValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/DataTypeValidator.java
index 606cf00..4e4a82a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/DataTypeValidator.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/DataTypeValidator.java
@@ -36,37 +36,80 @@
   @Check public void checkValueOfDefaultTypeMatchesFieldType(FieldOption option) {
     if (fieldOptions.isDefaultValueOption(option)) {
       MessageField field = (MessageField) option.eContainer();
-      INode nodeForValueFeature = nodes.firstNodeForFeature(option, FIELD_OPTION__VALUE);
-      checkValueTypeMatchesFieldType(option.getValue(), nodeForValueFeature, field);
+      checkValueTypeMatchesFieldType(option, field);
     }
   }
 
-  private  void checkValueTypeMatchesFieldType(Value value, INode nodeForValueFeature, MessageField field) {
-    if (messageFields.isString(field)) {
-      if (!(value instanceof StringLink)) {
-        error(expectedString, FIELD_OPTION__VALUE);
-      }
-      return;
+  private  void checkValueTypeMatchesFieldType(FieldOption option, MessageField field) {
+    if (validateBool(option, field)) return;
+    if (validateFloatingPointNumber(option, field)) return;
+    if (validateInteger(option, field)) return;
+    if (validateString(option, field)) return;
+    validateEnumLiteral(option, field);
+  }
+
+  private boolean validateBool(FieldOption option, MessageField field) {
+    if (!messageFields.isBool(field)) return false;
+    Value value = option.getValue();
+    if (!(value instanceof BooleanLink)) {
+      error(expectedTrueOrFalse, FIELD_OPTION__VALUE);
     }
-    if (messageFields.isBool(field)) {
-      if (!(value instanceof BooleanLink)) {
-        error(expectedTrueOrFalse, FIELD_OPTION__VALUE);
-      }
-      return;
+    return true;
+  }
+
+  private boolean validateFloatingPointNumber(FieldOption option, MessageField field) {
+    if (!messageFields.isFloatingPointNumber(field)) return false;
+    Value value = option.getValue();
+    if (!(value instanceof DoubleLink) && !(value instanceof LongLink)) {
+      error(expectedNumber, FIELD_OPTION__VALUE);
     }
+    return true;
+  }
+
+  private boolean validateInteger(FieldOption option, MessageField field) {
+    if (!messageFields.isInteger(field)) return false;
+    Value value = option.getValue();
+    if (!(value instanceof LongLink)) {
+      error(expectedInteger, FIELD_OPTION__VALUE);
+      return true;
+    }
+    if (messageFields.isUnsignedInteger(field)) {
+      Long longValue = ((LongLink) value).getTarget();
+      if (longValue < 0) {
+        error(expectedPositiveNumber, FIELD_OPTION__VALUE);
+      }
+    }
+    return true;
+  }
+
+  private boolean validateString(FieldOption option, MessageField field) {
+    if (!messageFields.isString(field)) return false;
+    Value value = option.getValue();
+    if (!(value instanceof StringLink)) {
+      error(expectedString, FIELD_OPTION__VALUE);
+    }
+    return true;
+  }
+
+  private boolean validateEnumLiteral(FieldOption option, MessageField field) {
+    Value value = option.getValue();
     Enum anEnum = modelFinder.enumTypeOf(field);
-    if (anEnum != null) {
-      if (!(value instanceof LiteralLink)) {
-        error(expectedIdentifier, FIELD_OPTION__VALUE);
-      }
-      Literal literal = ((LiteralLink) value).getTarget();
-      if (!anEnum.equals(literal.eContainer())) {
-        QualifiedName enumFqn = fqnProvider.getFullyQualifiedName(anEnum);
-        String literalName = nodes.textOf(nodeForValueFeature);
-        String msg = String.format(literalNotInEnum, enumFqn, literalName);
-        error(msg, FIELD_OPTION__VALUE);
-      }
-      return;
+    if (anEnum == null) return false;
+    if (!(value instanceof LiteralLink)) {
+      error(expectedIdentifier, FIELD_OPTION__VALUE);
+      return true;
     }
+    Literal literal = ((LiteralLink) value).getTarget();
+    if (!anEnum.equals(literal.eContainer())) {
+      QualifiedName enumFqn = fqnProvider.getFullyQualifiedName(anEnum);
+      String literalName = nodes.textOf(nodeForValueFeatureIn(option));
+      String msg = String.format(literalNotInEnum, enumFqn, literalName);
+      error(msg, FIELD_OPTION__VALUE);
+    }
+    return true;
+  }
+
+  private INode nodeForValueFeatureIn(FieldOption option) {
+    return nodes.firstNodeForFeature(option, FIELD_OPTION__VALUE);
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java
index cef1009..ed62dc8 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java
@@ -18,6 +18,9 @@
   public static String expectedFieldName;
   public static String expectedFieldNumber;
   public static String expectedIdentifier;
+  public static String expectedInteger;
+  public static String expectedNumber;
+  public static String expectedPositiveNumber;
   public static String expectedString;
   public static String expectedSyntaxIdentifier;
   public static String expectedTrueOrFalse;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties
index 497a7cd..105a56a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties
@@ -1,6 +1,9 @@
 expectedFieldName = Expected field name.
 expectedFieldNumber = Expected field number.
 expectedIdentifier = Expected identifier.
+expectedInteger = Expected integer.
+expectedNumber = Expected number.
+expectedPositiveNumber = Unsigned field can't have negative default value.
 expectedString = Expected string.
 expectedSyntaxIdentifier = Expected syntax identifier.
 expectedTrueOrFalse = Expected "true" or "false".