Fixed: [ Issue 86 ] Bugs with automatic field number generation when
pressing semicolon.

Made some progress on the formatter.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
index 43c9b7f..efa8277 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
@@ -8,11 +8,14 @@
  */
 package com.google.eclipse.protobuf.ui.builder;
 
+import static com.google.eclipse.protobuf.util.CommonWords.space;
+
 import java.util.*;
 
 import org.eclipse.core.resources.*;
 
 import com.google.eclipse.protobuf.ui.preferences.pages.compiler.SupportedLanguage;
+import com.google.eclipse.protobuf.util.CommonWords;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -29,14 +32,14 @@
   String protocCommand(IFile protoFile, String protocPath, List<String> importRoots,
       OutputDirectories outputDirectories) {
     StringBuilder command = new StringBuilder();
-    command.append(protocPath).append(" ");
+    command.append(protocPath).append(space());
     for (String importRoot : importRoots) {
-      command.append("-I=").append(importRoot).append(" ");
+      command.append("-I=").append(importRoot).append(space());
     }
     for (SupportedLanguage language : SupportedLanguage.values()) {
       IFolder outputDirectory = outputDirectories.outputDirectoryFor(language);
       if (outputDirectory == null) continue;
-      command.append(langOutFlag(language)).append(outputDirectory.getLocation().toOSString()).append(" ");
+      command.append(langOutFlag(language)).append(outputDirectory.getLocation().toOSString()).append(space());
     }
     command.append(protoFile.getLocation().toOSString());
     return command.toString();
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
index 1c661ff..abc31c1 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
@@ -19,6 +19,7 @@
 import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
 import org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory;
 import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+import org.eclipse.xtext.validation.IConcreteSyntaxValidator.InvalidConcreteSyntaxException;
 
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.ui.util.*;
@@ -51,9 +52,10 @@
       behaveLikeRegularEditing(styledText, originalCaretOffset);
       return;
     }
+    String content = contentToInsert(editor, originalCaretOffset);
+    if (content == null) return;
     int endOfLineOffset = offsetAtLine + line.length();
     styledText.setCaretOffset(endOfLineOffset);
-    String content = contentToInsert(editor, originalCaretOffset);
     insert(styledText, content, endOfLineOffset);
   }
 
@@ -67,41 +69,39 @@
   }
 
   private String contentToInsert(final XtextEditor editor, final int offset) {
-    return editor.getDocument().modify(new IUnitOfWork<String, XtextResource>() {
-      public String exec(XtextResource state) {
-        ContentAssistContext[] context = contextFactory.create(editor.getInternalSourceViewer(), offset, state);
-        if (context == null || context.length == 0) return semicolon;
-        for (ContentAssistContext c : context) {
-          EObject model = c.getCurrentModel();
-          if (model instanceof Literal)
-            return contentToInsert((Literal) model);
-          if (model instanceof Property)
-            return contentToInsert((Property) model);
+    try {
+      return editor.getDocument().modify(new IUnitOfWork<String, XtextResource>() {
+        public String exec(XtextResource state) {
+          ContentAssistContext[] context = contextFactory.create(editor.getInternalSourceViewer(), offset, state);
+          if (context == null || context.length == 0) return semicolon;
+          for (ContentAssistContext c : context) {
+            EObject model = c.getCurrentModel();
+            if (model instanceof Literal)
+              return contentToInsert((Literal) model);
+            if (model instanceof Property)
+              return contentToInsert((Property) model);
+          }
+          return semicolon;
         }
-        return semicolon;
-      }
-    });
+      });
+    } catch (InvalidConcreteSyntaxException e) {
+      return null;
+    }
   }
 
   private String contentToInsert(Literal literal) {
     INode indexNode = nodes.firstNodeForFeature(literal, LITERAL__INDEX);
     if (indexNode != null) return semicolon;
     int index = literals.calculateIndexOf(literal);
-    return defaultIndexAndSemicolonToInsert(index);
+    literal.setIndex(index);
+    return null;
   }
 
   private String contentToInsert(Property property) {
     INode indexNode = nodes.firstNodeForFeature(property, FIELD__INDEX);
     if (indexNode != null) return semicolon;
     int index = fields.calculateTagNumberOf(property);
-    return defaultIndexAndSemicolonToInsert(index);
-  }
-
-  private String defaultIndexAndSemicolonToInsert(int index) {
-    return indexAndSemicolonToInsert("= %d%s", index);
-  }
-
-  private String indexAndSemicolonToInsert(String format, int index) {
-    return String.format(format, index, semicolon);
+    property.setIndex(index);
+    return null;
   }
 }
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 60a82bc..95a4b49 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
@@ -12,6 +12,7 @@
 import static com.google.eclipse.protobuf.protobuf.Modifier.*;
 import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.*;
 import static com.google.eclipse.protobuf.ui.util.Strings.firstCharToLowerCase;
+import static com.google.eclipse.protobuf.util.CommonWords.space;
 import static java.lang.String.valueOf;
 import static java.util.Collections.emptyList;
 import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
@@ -44,8 +45,6 @@
  */
 public class ProtobufProposalProvider extends AbstractProtobufProposalProvider {
 
-  private static final String SPACE = " ";
-
   @Inject private ProtobufElementFinder finder;
   @Inject private ProtoDescriptorProvider descriptorProvider;
   @Inject private PluginImageHelper imageHelper;
@@ -66,7 +65,7 @@
 
   @Override public void complete_Syntax(EObject model, RuleCall ruleCall, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
-    String proposal = SYNTAX + SPACE + EQUAL_PROTO2_IN_QUOTES;
+    String proposal = SYNTAX + space() + EQUAL_PROTO2_IN_QUOTES;
     proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor);
   }
 
@@ -359,7 +358,7 @@
 
   private void proposeOption(Property option, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
     String displayString = option.getName();
-    String proposalText = displayString + SPACE + EQUAL + SPACE;
+    String proposalText = displayString + space() + EQUAL + space();
     boolean isStringOption = properties.isString(option);
     if (isStringOption) {
       proposalText = proposalText + EMPTY_STRING;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
index 0efb3ed..58598c3 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
@@ -8,6 +8,7 @@
  */
 package com.google.eclipse.protobuf.ui.documentation;
 
+import static com.google.eclipse.protobuf.util.CommonWords.space;
 import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
 
 import org.eclipse.emf.ecore.EObject;
@@ -17,6 +18,7 @@
 
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.scoping.*;
+import com.google.eclipse.protobuf.util.CommonWords;
 import com.google.inject.Inject;
 
 /**
@@ -76,7 +78,7 @@
 
   private String cleanUp(String comment) {
     return comment.replaceFirst(COMMENT_START, "")
-                  .replaceAll(WINDOWS_NEW_LINE, " ")
-                  .replaceAll(UNIX_NEW_LINE, " ");
+                  .replaceAll(WINDOWS_NEW_LINE, space())
+                  .replaceAll(UNIX_NEW_LINE, space());
   }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/grammar/CompoundElement.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/grammar/CompoundElement.java
index 62b1046..03b555e 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/grammar/CompoundElement.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/grammar/CompoundElement.java
@@ -9,8 +9,10 @@
 package com.google.eclipse.protobuf.ui.grammar;
 
 import static com.google.eclipse.protobuf.grammar.CommonKeyword.*;
+import static com.google.eclipse.protobuf.util.CommonWords.space;
 
 import com.google.eclipse.protobuf.grammar.CommonKeyword;
+import com.google.eclipse.protobuf.util.CommonWords;
 
 /**
  * Element composed of one or more keywords.
@@ -28,8 +30,6 @@
   PROTO2_IN_QUOTES(join(QUOTE, "proto2", QUOTE, SEMICOLON)),
   EQUAL_PROTO2_IN_QUOTES(joinWithWhitespace(EQUAL, PROTO2_IN_QUOTES));
 
-  private static final String SPACE = " ";
-
   private final String value;
 
   private static String join(Object...objects) {
@@ -47,7 +47,7 @@
     for (int i = 0; i < count; i++) {
       String s = objects[i].toString();
       buffer.append(s);
-      if (i < count - 1 && !s.endsWith(SPACE)) buffer.append(SPACE);
+      if (i < count - 1 && !s.endsWith(space())) buffer.append(space());
     }
     return buffer.toString();
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
index a858b4d..a40797c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
@@ -1,27 +1,90 @@
 /*
  * Copyright (c) 2011 Google 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
- *
+ * 
+ * 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
  */
 package com.google.eclipse.protobuf.formatting;
 
+import static com.google.eclipse.protobuf.grammar.CommonKeyword.*;
+import static com.google.eclipse.protobuf.util.CommonWords.space;
+
+import com.google.eclipse.protobuf.services.*;
+import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.EnumElements;
+import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ExtendMessageElements;
+import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.MessageElements;
+import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.RpcElements;
+import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ServiceElements;
+
+import org.eclipse.xtext.Keyword;
 import org.eclipse.xtext.formatting.impl.*;
 
-import com.google.eclipse.protobuf.services.ProtobufGrammarAccess;
-
 /**
- * This class contains custom formatting description.
- *
+ * This class provides custom formatting.
+ * 
  * @see <a href="http://www.eclipse.org/Xtext/documentation/2_0_0/105-formatting.php">Xtext Formatting</a>
  */
 public class ProtobufFormatter extends AbstractDeclarativeFormatter {
 
-	@Override
-	protected void configureFormatting(FormattingConfig c) {
-	  ProtobufGrammarAccess g = (ProtobufGrammarAccess) getGrammarAccess();
-	  c.setLinewrap(0, 1, 2).before(g.getSL_COMMENTRule());
-	}
+  @Override protected void configureFormatting(FormattingConfig c) {
+    ProtobufGrammarAccess g = (ProtobufGrammarAccess) getGrammarAccess();
+    c.setLinewrap(0, 1, 2).before(g.getSL_COMMENTRule());
+    c.setLinewrap(1).after(g.getPropertyRule());
+    for (Keyword equal : g.findKeywords(EQUAL.toString())) {
+      c.setSpace(space()).around(equal);
+    }
+    for (Keyword semicolon : g.findKeywords(SEMICOLON.toString())) {
+      c.setNoSpace().before(semicolon);
+    }
+    for (Keyword openingBrace : g.findKeywords("{")) {
+      c.setLinewrap(1).after(openingBrace);
+    }
+    for (Keyword closingBrace : g.findKeywords("}")) {
+      c.setLinewrap(2).after(closingBrace);
+    }
+    for (Keyword openingBracket : g.findKeywords(OPENING_BRACKET.toString())) {
+      c.setNoSpace().after(openingBracket);
+    }
+    for (Keyword closingBracket : g.findKeywords(CLOSING_BRACKET.toString())) {
+      c.setNoSpace().before(closingBracket);
+    }
+    indentMessageElements(c, g);
+    indentExtendMessageElements(c, g);
+    indentEnumElements(c, g);
+    indentServiceElements(c, g);
+    indentRpcElements(c, g);
+  }
+
+  private void indentMessageElements(FormattingConfig c, ProtobufGrammarAccess g) {
+    MessageElements e = g.getMessageAccess();
+    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
+    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
+  }
+  
+  private void indentExtendMessageElements(FormattingConfig c, ProtobufGrammarAccess g) {
+    ExtendMessageElements e = g.getExtendMessageAccess();
+    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
+    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
+  }
+  
+  private void indentEnumElements(FormattingConfig c, ProtobufGrammarAccess g) {
+    EnumElements e = g.getEnumAccess();
+    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
+    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
+  }
+
+  private void indentServiceElements(FormattingConfig c, ProtobufGrammarAccess g) {
+    ServiceElements e = g.getServiceAccess();
+    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
+    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
+  }
+
+  private void indentRpcElements(FormattingConfig c, ProtobufGrammarAccess g) {
+    RpcElements e = g.getRpcAccess();
+    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_9_0_0_0());
+    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_9_0_0_2());
+  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Closeables.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Closeables.java
index 7fdb025..1065f29 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Closeables.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Closeables.java
@@ -1,6 +1,9 @@
 /*
- * Copyright (c) 2011 Google 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
+ * Copyright (c) 2011 Google 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
  */
 package com.google.eclipse.protobuf.util;
@@ -8,12 +11,17 @@
 import java.io.*;
 
 /**
- * Utility methods related to <code>{@link Closeable}</code>.
+ * Utility methods related to <code>{@link Closeable}</code>s.
  * 
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class Closeables {
   
+  /**
+   * Invokes {@code close()} on the given <code>{@link Cloneable}</code>, ignoring any thrown exceptions.
+   * @param c the given {@code Closeable}.
+   * @return {@code false} if the given {@code Closeable} was {@code null}; {@code true} otherwise.
+   */
   public static boolean close(Closeable c) {
     if (c == null) return false;
     try {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/CommonWords.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/CommonWords.java
new file mode 100644
index 0000000..4ad10b4
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/CommonWords.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Google 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
+ */
+package com.google.eclipse.protobuf.util;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public final class CommonWords {
+
+  private static final String SPACE = " ";
+  
+  /**
+   * Returns a single space.
+   * @return a single space.
+   */
+  public static String space() {
+    return SPACE;
+  }
+  
+  private CommonWords() {}
+}