Add support for 'syntax = "proto3";'

Change-Id: Ie032e2b429d59833eda0c022e2412f15c1b4e1a5
Signed-off-by: Harry Terkelsen <het@google.com>
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_Test.java
similarity index 86%
rename from com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_Test.java
rename to com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_Test.java
index 4e34996..efce405 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2014 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
@@ -24,11 +24,11 @@
 import com.google.inject.Inject;
 
 /**
- * Tests for <code>{@link ImportValidator#checkNonProto2Imports(Protobuf)}</code>
+ * Tests for <code>{@link ImportValidator#checkUnknownSyntaxImports(Protobuf)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ImportValidator_checkNonProto2Imports_Test {
+public class ImportValidator_checkUnknownSyntaxImports_Test {
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule());
 
   @Inject private ImportValidator validator;
@@ -54,7 +54,7 @@
   // import "B.proto";
   // import "C.proto";
   @Test public void should_not_add_warnings_if_imported_files_are_proto2() {
-    validator.checkNonProto2Imports(xtext.root());
+    validator.checkUnknownSyntaxImports(xtext.root());
     verifyNoMoreInteractions(messageAcceptor);
   }
 
@@ -75,7 +75,7 @@
   // import "B.proto";
   // import "C.proto";
   @Test public void should_not_add_warnings_if_imported_files_are_proto2_even_with_circular_dependencies() {
-    validator.checkNonProto2Imports(xtext.root());
+    validator.checkUnknownSyntaxImports(xtext.root());
     verifyNoMoreInteractions(messageAcceptor);
   }
 
@@ -83,7 +83,7 @@
   //
   // import "093651b0-5676-11e1-b86c-0800200c9a66.proto";
   @Test public void should_not_add_warnings_if_imported_file_does_not_exist() {
-    validator.checkNonProto2Imports(xtext.root());
+    validator.checkUnknownSyntaxImports(xtext.root());
     verifyNoMoreInteractions(messageAcceptor);
   }
 }
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_withNonProto2Imports_Tests.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_withNonProto2Imports_Tests.java
similarity index 67%
rename from com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_withNonProto2Imports_Tests.java
rename to com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_withNonProto2Imports_Tests.java
index 8ca9ade..67e844f 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkNonProto2Imports_withNonProto2Imports_Tests.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/validation/ImportValidator_checkUnknownSyntaxImports_withNonProto2Imports_Tests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2014 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
@@ -15,7 +15,7 @@
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI;
-import static com.google.eclipse.protobuf.validation.Messages.importingNonProto2;
+import static com.google.eclipse.protobuf.validation.Messages.importingUnsupportedSyntax;
 
 import java.util.List;
 
@@ -34,11 +34,11 @@
 import com.google.inject.Singleton;
 
 /**
- * Tests for <code>{@link ImportValidator#checkNonProto2Imports(Protobuf)}</code>
+ * Tests for <code>{@link ImportValidator#checkUnknownSyntaxImports(Protobuf)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ImportValidator_checkNonProto2Imports_withNonProto2Imports_Tests {
+public class ImportValidator_checkUnknownSyntaxImports_withNonProto2Imports_Tests {
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule(), new TestModule());
 
   @Inject private ProtobufsStub protobufs;
@@ -63,11 +63,11 @@
   //
   // import "B.proto";
   // import "C.proto";
-  @Test public void should_add_warning_if_import_if_import_refers_directly_to_non_proto2() {
-    protobufs.nonProto2FileName = "B.proto";
-    validator.checkNonProto2Imports(xtext.root());
-    Import importWithNonProto2File = findImportReferreringToFile(protobufs.nonProto2FileName);
-    verifyThatImportingNonProto2FileCreatedWarning(importWithNonProto2File);
+  @Test public void should_add_warning_if_import_refers_directly_to_unknown_syntax() {
+    protobufs.unknownSyntaxFileName = "B.proto";
+    validator.checkUnknownSyntaxImports(xtext.root());
+    Import importWithUnknownSyntaxFile = findImportReferreringToFile(protobufs.unknownSyntaxFileName);
+    verifyThatImportingUnknownSyntaxFileCreatedWarning(importWithUnknownSyntaxFile);
   }
 
   // // Create file C.proto
@@ -83,11 +83,11 @@
   // syntax = "proto2";
   //
   // import "B.proto";
-  @Test public void should_add_warning_if_import_if_import_refers_indirectly_to_non_proto2() {
-    protobufs.nonProto2FileName = "C.proto";
-    validator.checkNonProto2Imports(xtext.root());
-    Import importWithNonProto2File = findImportReferreringToFile("B.proto");
-    verifyThatImportingNonProto2FileCreatedWarning(importWithNonProto2File);
+  @Test public void should_add_warning_if_import_refers_indirectly_to_unknown_syntax() {
+    protobufs.unknownSyntaxFileName = "C.proto";
+    validator.checkUnknownSyntaxImports(xtext.root());
+    Import importWithUnknownSyntaxFile = findImportReferreringToFile("B.proto");
+    verifyThatImportingUnknownSyntaxFileCreatedWarning(importWithUnknownSyntaxFile);
   }
 
   private Import findImportReferreringToFile(String fileName) {
@@ -100,8 +100,8 @@
     return null;
   }
 
-  private void verifyThatImportingNonProto2FileCreatedWarning(Import anImport) {
-    verify(messageAcceptor).acceptWarning(importingNonProto2, anImport, IMPORT__IMPORT_URI, INSIGNIFICANT_INDEX, null,
+  private void verifyThatImportingUnknownSyntaxFileCreatedWarning(Import anImport) {
+    verify(messageAcceptor).acceptWarning(importingUnsupportedSyntax, anImport, IMPORT__IMPORT_URI, INSIGNIFICANT_INDEX, null,
         new String[0]);
   }
 
@@ -112,14 +112,14 @@
   }
 
   @Singleton private static class ProtobufsStub extends Protobufs {
-    String nonProto2FileName;
+    String unknownSyntaxFileName;
 
-    @Override public boolean isProto2(Protobuf protobuf) {
+    @Override public boolean hasKnownSyntax(Protobuf protobuf) {
       URI resourceUri = protobuf.eResource().getURI();
-      if (resourceUri.toString().endsWith(nonProto2FileName)) {
+      if (resourceUri.toString().endsWith(unknownSyntaxFileName)) {
         return false;
       }
-      return super.isProto2(protobuf);
+      return super.hasKnownSyntax(protobuf);
     }
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Proto3SyntaxTest.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Proto3SyntaxTest.java
new file mode 100644
index 0000000..5a62470
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Proto3SyntaxTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 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.bugs;
+
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static org.junit.Assert.assertTrue;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.validation.ProtobufJavaValidator;
+import com.google.inject.Inject;
+
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Test that the parser correctly handles proto3 syntax.
+ */
+public class Proto3SyntaxTest {
+  @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
+
+  @Inject private ProtobufJavaValidator validator;
+
+  // syntax = "proto3";
+  //
+  // message Foo {
+  //   optional string bar = 1;
+  // }
+  @Test public void shouldAllowProto3Syntax() {
+    boolean isValid = validator.validate(xtext.root(), new BasicDiagnostic(), null);
+    assertTrue(isValid);
+  }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/Syntaxes_proto3_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/Syntaxes_proto3_Test.java
new file mode 100644
index 0000000..66c9a06
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/Syntaxes_proto3_Test.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 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.grammar;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+/**
+ * Tests for <code>{@link Syntaxes#proto3()}</code>.
+ */
+public class Syntaxes_proto3_Test {
+  @Test public void should_return_proto3() {
+    assertThat(Syntaxes.proto3(), equalTo("proto3"));
+  }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsProto2_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsKnown_Test.java
similarity index 65%
rename from com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsProto2_Test.java
rename to com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsKnown_Test.java
index f972764..ff0ae0c 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsProto2_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkSyntaxIsKnown_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2014 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
@@ -8,27 +8,26 @@
  */
 package com.google.eclipse.protobuf.validation;
 
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.SYNTAX__NAME;
+import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.SYNTAX_IS_NOT_KNOWN_ERROR;
 import static org.eclipse.xtext.validation.ValidationMessageAcceptor.INSIGNIFICANT_INDEX;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.SYNTAX__NAME;
-import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.SYNTAX_IS_NOT_PROTO2_ERROR;
+import com.google.eclipse.protobuf.protobuf.Syntax;
 
 import org.eclipse.xtext.validation.ValidationMessageAcceptor;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.eclipse.protobuf.protobuf.Syntax;
-
 /**
- * Tests for <code>{@link ProtobufJavaValidator#checkSyntaxIsProto2(Syntax)}</code>
+ * Tests for <code>{@link ProtobufJavaValidator#checkSyntaxIsKnown(Syntax)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ProtobufJavaValidator_checkSyntaxIsProto2_Test {
+public class ProtobufJavaValidator_checkSyntaxIsKnown_Test {
   private Syntax syntax;
   private ValidationMessageAcceptor messageAcceptor;
   private ProtobufJavaValidator validator;
@@ -40,16 +39,22 @@
     validator.setMessageAcceptor(messageAcceptor);
   }
 
-  @Test public void should_create_error_if_syntax_is_not_proto2() {
-    when(syntax.getName()).thenReturn("proto1");
-    validator.checkSyntaxIsProto2(syntax);
-    String message = "Unrecognized syntax identifier \"proto1\".  This parser only recognizes \"proto2\".";
-    verify(messageAcceptor).acceptError(message, syntax, SYNTAX__NAME, INSIGNIFICANT_INDEX, SYNTAX_IS_NOT_PROTO2_ERROR);
+  @Test public void should_create_error_if_syntax_is_not_proto2_or_proto3() {
+    when(syntax.getName()).thenReturn("proto5");
+    validator.checkSyntaxIsKnown(syntax);
+    String message = "Unrecognized syntax identifier \"proto5\".  This parser only recognizes \"proto2\" or \"proto3\".";
+    verify(messageAcceptor).acceptError(message, syntax, SYNTAX__NAME, INSIGNIFICANT_INDEX, SYNTAX_IS_NOT_KNOWN_ERROR);
   }
 
   @Test public void should_not_create_error_if_syntax_is_proto2() {
     when(syntax.getName()).thenReturn("proto2");
-    validator.checkSyntaxIsProto2(syntax);
+    validator.checkSyntaxIsKnown(syntax);
+    verifyZeroInteractions(messageAcceptor);
+  }
+
+  @Test public void should_not_create_error_if_syntax_is_proto3() {
+    when(syntax.getName()).thenReturn("proto3");
+    validator.checkSyntaxIsKnown(syntax);
     verifyZeroInteractions(messageAcceptor);
   }
 }
diff --git a/com.google.eclipse.protobuf.ui.integration.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java b/com.google.eclipse.protobuf.ui.integration.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
index f9e7291..2323b60 100644
--- a/com.google.eclipse.protobuf.ui.integration.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
+++ b/com.google.eclipse.protobuf.ui.integration.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
@@ -25,7 +25,7 @@
 
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.junit.util.MultiLineTextBuilder;
-import com.google.eclipse.protobuf.parser.NonProto2Protobuf;
+import com.google.eclipse.protobuf.parser.UnknownSyntaxProtobuf;
 import com.google.eclipse.protobuf.protobuf.Protobuf;
 import com.google.eclipse.protobuf.ui.plugin.ProtobufEditorPlugIn;
 import com.google.inject.Inject;
@@ -58,7 +58,7 @@
     store.setValue("misc.googleInternal", true);
     xtext.parseText(proto1);
     Protobuf root = xtext.root();
-    assertThat(root, instanceOf(NonProto2Protobuf.class));
+    assertThat(root, instanceOf(UnknownSyntaxProtobuf.class));
   }
 
   @Test public void should_not_recognize_proto1_syntax() {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/SmartSemicolonHandler.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/SmartSemicolonHandler.java
index 5c21247..149425c 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/SmartSemicolonHandler.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/SmartSemicolonHandler.java
@@ -100,7 +100,7 @@
       document.modify(new IUnitOfWork.Void<XtextResource>() {
         @Override public void process(XtextResource resource) {
           Protobuf root = resources.rootOf(resource);
-          if (!protobufs.isProto2(root) /*|| !resource.getErrors().isEmpty()*/) {
+          if (!protobufs.hasKnownSyntax(root)) {
             return;
           }
           int offset = styledTextAccess.caretOffset();
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 defd152..bbbce17 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
@@ -29,6 +29,8 @@
 import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.EMPTY_STRING;
 import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.EQUAL_PROTO2_IN_QUOTES;
 import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.PROTO2_IN_QUOTES;
+import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.EQUAL_PROTO3_IN_QUOTES;
+import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.PROTO3_IN_QUOTES;
 import static com.google.eclipse.protobuf.util.CommonWords.space;
 import static java.lang.String.valueOf;
 import static java.util.Collections.emptyList;
@@ -111,12 +113,16 @@
   @Override public void completeSyntax_Name(EObject model, Assignment assignment, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
     proposeAndAccept(PROTO2_IN_QUOTES, context, acceptor);
+    proposeAndAccept(PROTO3_IN_QUOTES, context, acceptor);
   }
 
   @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)), context, acceptor);
+    
+    proposal = SYNTAX + space() + EQUAL_PROTO3_IN_QUOTES;
+    proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(SYNTAX)), context, acceptor);
   }
 
   @Override public void completeComplexTypeLink_Target(EObject model, Assignment assignment,
@@ -220,6 +226,7 @@
       EObject grammarElement = context.getLastCompleteNode().getGrammarElement();
       if (isKeyword(grammarElement, SYNTAX)) {
         proposeEqualProto2(context, acceptor);
+        proposeEqualProto3(context, acceptor);
       }
       return true;
     }
@@ -265,6 +272,10 @@
   private void proposeEqualProto2(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
     proposeAndAccept(EQUAL_PROTO2_IN_QUOTES, context, acceptor);
   }
+  
+  private void proposeEqualProto3(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+    proposeAndAccept(EQUAL_PROTO3_IN_QUOTES, context, acceptor);
+  }
 
   private void proposeAndAccept(CompoundElement proposalText, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
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 f5a1915..dfa1a0c 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
@@ -31,7 +31,9 @@
   DEFAULT_EQUAL_STRING(joinWithWhitespace(DEFAULT_EQUAL, EMPTY_STRING)),
   DEFAULT_EQUAL_STRING_IN_BRACKETS(inBrackets(DEFAULT_EQUAL_STRING)),
   PROTO2_IN_QUOTES(join(QUOTE, proto2(), QUOTE, SEMICOLON)),
-  EQUAL_PROTO2_IN_QUOTES(joinWithWhitespace(EQUAL, PROTO2_IN_QUOTES));
+  EQUAL_PROTO2_IN_QUOTES(joinWithWhitespace(EQUAL, PROTO2_IN_QUOTES)),
+  PROTO3_IN_QUOTES(join(QUOTE, proto2(), QUOTE, SEMICOLON)),
+  EQUAL_PROTO3_IN_QUOTES(joinWithWhitespace(EQUAL, PROTO2_IN_QUOTES));
 
   private final String value;
 
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser.java
index 345e829..9145d8c 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser.java
@@ -15,7 +15,7 @@
 import org.eclipse.xtext.parser.ParseResult;
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 
-import com.google.eclipse.protobuf.parser.NonProto2Protobuf;
+import com.google.eclipse.protobuf.parser.UnknownSyntaxProtobuf;
 import com.google.eclipse.protobuf.parser.antlr.ProtobufParser;
 import com.google.eclipse.protobuf.protobuf.Protobuf;
 import com.google.eclipse.protobuf.ui.preferences.misc.MiscellaneousPreferences;
@@ -31,13 +31,13 @@
       int initialLookAhead) {
     IParseResult result = super.doParse(ruleName, in, builder, initialLookAhead);
     MiscellaneousPreferences preferences = new MiscellaneousPreferences(storeAccess);
-    if (preferences.isGoogleInternal() && isNotProto2(result)) {
-      return new ParseResult(new NonProto2Protobuf(), result.getRootNode(), false);
+    if (preferences.isGoogleInternal() && hasUnknownSyntax(result)) {
+      return new ParseResult(new UnknownSyntaxProtobuf(), result.getRootNode(), false);
     }
     return result;
   }
 
-  private boolean isNotProto2(IParseResult result) {
+  private boolean hasUnknownSyntax(IParseResult result) {
     EObject rootObj = result.getRootASTElement();
     if (rootObj instanceof Protobuf) {
       Protobuf root = (Protobuf) result.getRootASTElement();
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
index af62eee..32e012c 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
@@ -8,10 +8,8 @@
  */
 package com.google.eclipse.protobuf.ui.quickfix;
 
-import static org.eclipse.emf.ecore.util.EcoreUtil.remove;
-import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.findActualNodeFor;
-
 import static com.google.eclipse.protobuf.grammar.Syntaxes.proto2;
+import static com.google.eclipse.protobuf.grammar.Syntaxes.proto3;
 import static com.google.eclipse.protobuf.protobuf.BOOL.FALSE;
 import static com.google.eclipse.protobuf.protobuf.BOOL.TRUE;
 import static com.google.eclipse.protobuf.ui.quickfix.Messages.changeValueDescription;
@@ -24,19 +22,9 @@
 import static com.google.eclipse.protobuf.validation.DataTypeValidator.EXPECTED_STRING_ERROR;
 import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.INVALID_FIELD_TAG_NUMBER_ERROR;
 import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.MORE_THAN_ONE_PACKAGE_ERROR;
-import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.SYNTAX_IS_NOT_PROTO2_ERROR;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.resource.XtextResource;
-import org.eclipse.xtext.ui.editor.model.IXtextDocument;
-import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
-import org.eclipse.xtext.ui.editor.model.edit.ISemanticModification;
-import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider;
-import org.eclipse.xtext.ui.editor.quickfix.Fix;
-import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
-import org.eclipse.xtext.util.concurrent.IUnitOfWork;
-import org.eclipse.xtext.validation.Issue;
+import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.SYNTAX_IS_NOT_KNOWN_ERROR;
+import static org.eclipse.emf.ecore.util.EcoreUtil.remove;
+import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.findActualNodeFor;
 
 import com.google.eclipse.protobuf.grammar.CommonKeyword;
 import com.google.eclipse.protobuf.model.util.INodes;
@@ -53,6 +41,18 @@
 import com.google.eclipse.protobuf.protobuf.Value;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.ui.editor.model.IXtextDocument;
+import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
+import org.eclipse.xtext.ui.editor.model.edit.ISemanticModification;
+import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider;
+import org.eclipse.xtext.ui.editor.quickfix.Fix;
+import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
+import org.eclipse.xtext.util.concurrent.IUnitOfWork;
+import org.eclipse.xtext.validation.Issue;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -63,7 +63,7 @@
   @Inject private NameResolver nameResolver;
   @Inject private INodes nodes;
 
-  @Fix(SYNTAX_IS_NOT_PROTO2_ERROR)
+  @Fix(SYNTAX_IS_NOT_KNOWN_ERROR)
   public void changeSyntaxToProto2(Issue issue, IssueResolutionAcceptor acceptor) {
     ISemanticModification modification = new ISemanticModification() {
       @Override public void apply(EObject element, IModificationContext context) throws Exception {
@@ -76,6 +76,19 @@
     acceptor.accept(issue, label, description, ICON_FOR_CHANGE, modification);
   }
 
+  @Fix(SYNTAX_IS_NOT_KNOWN_ERROR)
+  public void changeSyntaxToProto3(Issue issue, IssueResolutionAcceptor acceptor) {
+    ISemanticModification modification = new ISemanticModification() {
+      @Override public void apply(EObject element, IModificationContext context) throws Exception {
+        Syntax syntax = (Syntax) element;
+        syntax.setName(proto3());
+      }
+    };
+    String description = String.format(changeValueDescription, "syntax", quote(proto3()));
+    String label = String.format(changeValueLabel, proto3());
+    acceptor.accept(issue, label, description, ICON_FOR_CHANGE, modification);
+  }
+
   @Fix(INVALID_FIELD_TAG_NUMBER_ERROR)
   public void regenerateTagNumber(Issue issue, IssueResolutionAcceptor acceptor) {
     ISemanticModification modification = new ISemanticModification() {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/Syntaxes.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/Syntaxes.java
index 342bf18..f27176a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/Syntaxes.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/Syntaxes.java
@@ -13,7 +13,7 @@
  */
 public final class Syntaxes {
   /**
-   * Returns the value to use to in the "syntax" element.
+   * Returns the value to use to in the "syntax" element if this is a proto2 file.
    * @return the {@code String} "proto2".
    */
   public static String proto2() {
@@ -21,6 +21,14 @@
   }
 
   /**
+   * Returns the value to use to in the "syntax" element if this is a proto3 file.
+   * @return the {@code String} "proto3".
+   */
+  public static String proto3() {
+    return "proto3";
+  }
+
+  /**
    * Indicates whether the given {@code String} is equal to <code>{@link #proto2()}</code>.
    * @param s the {@code String} to check.
    * @return {@code true} if the given {@code String} is equal to "proto2," {@code false} otherwise.
@@ -29,5 +37,14 @@
     return proto2().equals(s);
   }
 
+  /**
+   * Indicates whether the given {@code String} is equal to <code>{@link #proto3()}</code>.
+   * @param s the {@code String} to check.
+   * @return {@code true} if the given {@code String} is equal to "proto3," {@code false} otherwise.
+   */
+  public static boolean isSpecifyingProto3Syntax(String s) {
+    return proto3().equals(s);
+  }
+
   private Syntaxes() {}
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
index 7cb8688..cf77997 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
@@ -14,7 +14,7 @@
 
 import java.util.List;
 
-import com.google.eclipse.protobuf.parser.NonProto2Protobuf;
+import com.google.eclipse.protobuf.parser.UnknownSyntaxProtobuf;
 import com.google.eclipse.protobuf.protobuf.Import;
 import com.google.eclipse.protobuf.protobuf.Protobuf;
 import com.google.eclipse.protobuf.protobuf.ProtobufElement;
@@ -28,13 +28,14 @@
  */
 @Singleton public class Protobufs {
   /**
-   * Indicates whether the given root is not {@code null} and has a "proto2" syntax element.
+   * Indicates whether the given root is not {@code null} and has a known syntax.
+   *
    * @param protobuf the given root.
-   * @return {@code true} if the given root is not {@code null} and has a "proto2" syntax element, {@code false}
-   * otherwise.
+   * @return {@code true} if the given root is not {@code null} and has a syntax element,
+   *         {@code false} otherwise.
    */
-  public boolean isProto2(Protobuf protobuf) {
-    return protobuf != null && !(protobuf instanceof NonProto2Protobuf);
+  public boolean hasKnownSyntax(Protobuf protobuf) {
+    return protobuf != null && !(protobuf instanceof UnknownSyntaxProtobuf);
   }
 
   /**
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/NonProto2Protobuf.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/UnknownSyntaxProtobuf.java
similarity index 61%
rename from com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/NonProto2Protobuf.java
rename to com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/UnknownSyntaxProtobuf.java
index 4ca44a4..e28a2a3 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/NonProto2Protobuf.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/parser/UnknownSyntaxProtobuf.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2014 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
@@ -11,14 +11,14 @@
 import com.google.eclipse.protobuf.protobuf.impl.ProtobufImpl;
 
 /**
- * Represents a non-proto2 protocol buffer, which is ignored by the editor.
+ * Represents an unknown syntax protocol buffer, which is ignored by the editor.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class NonProto2Protobuf extends ProtobufImpl {
+public class UnknownSyntaxProtobuf extends ProtobufImpl {
 
   /**
-   * Creates a new <code>{@link NonProto2Protobuf}</code>.
+   * Creates a new <code>{@link UnknownSyntaxProtobuf}</code>.
    */
-  public NonProto2Protobuf() {}
+  public UnknownSyntaxProtobuf() {}
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
index e121a84..f71e484 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
@@ -113,7 +113,7 @@
         continue;
       }
       Protobuf rootOfImported = resources.rootOf(imported);
-      if (!protobufs.isProto2(rootOfImported)) {
+      if (!protobufs.hasKnownSyntax(rootOfImported)) {
         continue;
       }
       if (rootOfImported != null) {
@@ -130,7 +130,7 @@
   }
 
   private <T> Collection<IEObjectDescription> publicImported(Protobuf start, FinderStrategy<T> strategy, T criteria) {
-    if (!protobufs.isProto2(start)) {
+    if (!protobufs.hasKnownSyntax(start)) {
       return emptySet();
     }
     List<Import> allImports = protobufs.publicImportsIn(start);
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ImportValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ImportValidator.java
index e630dd5..7ae7e45 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ImportValidator.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ImportValidator.java
@@ -16,7 +16,7 @@
 import static com.google.common.collect.Sets.newHashSet;
 import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI;
 import static com.google.eclipse.protobuf.validation.Messages.importNotFound;
-import static com.google.eclipse.protobuf.validation.Messages.importingNonProto2;
+import static com.google.eclipse.protobuf.validation.Messages.importingUnsupportedSyntax;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,75 +50,78 @@
   @Override public void register(EValidatorRegistrar registrar) {}
 
   /**
-   * Verifies that {@code Import}s in the given root only refer to "proto2" files. If non-proto2 {@code Import}s are
-   * found, this validator will create warning markers for such {@code Import}s.
+   * Verifies that {@code Import}s in the given root only refer to files with a supported syntax. If
+   * unsupported {@code Import}s are found, this validator will create warning markers for such
+   * {@code Import}s.
+   *
    * @param root the root containing the imports to check.
    */
-  @Check public void checkNonProto2Imports(Protobuf root) {
-    if (!protobufs.isProto2(root)) {
+  @Check public void checkUnknownSyntaxImports(Protobuf root) {
+    if (!protobufs.hasKnownSyntax(root)) {
       return;
     }
     Set<Protobuf> currentlyChecking = newHashSet(root);
-    HashMap<Protobuf, IsProto2> alreadyChecked = newHashMap();
-    hasNonProto2Imports(root, currentlyChecking, alreadyChecked);
+    HashMap<Protobuf, HasKnownSyntax> alreadyChecked = newHashMap();
+    hasUnknownSyntaxImports(root, currentlyChecking, alreadyChecked);
   }
 
-  private boolean hasNonProto2Imports(Protobuf root, Set<Protobuf> currentlyChecking,
-      Map<Protobuf, IsProto2> alreadyChecked) {
-    IsProto2 isProto2 = alreadyChecked.get(root);
-    if (isProto2 != null) {
-      return isProto2 == IsProto2.NO;
+  private boolean hasUnknownSyntaxImports(Protobuf root, Set<Protobuf> currentlyChecking,
+      Map<Protobuf, HasKnownSyntax> alreadyChecked) {
+    HasKnownSyntax hasKnownSyntax = alreadyChecked.get(root);
+    if (hasKnownSyntax != null) {
+      return hasKnownSyntax == HasKnownSyntax.NO;
     }
     currentlyChecking.add(root);
     Set<Pair<Import, Protobuf>> importsToCheck = newHashSet();
-    boolean hasNonProto2Imports = false;
+    boolean hasUnsupportedImports = false;
     for (Import anImport : protobufs.importsIn(root)) {
       Resource imported = imports.importedResource(anImport);
       if (imported == null) {
         continue;
       }
       Protobuf importedRoot = resources.rootOf(imported);
-      isProto2 = alreadyChecked.get(importedRoot);
-      if (isProto2 != null) {
+      hasKnownSyntax = alreadyChecked.get(importedRoot);
+      if (hasKnownSyntax != null) {
         // resource was already checked.
-        if (isProto2 == IsProto2.NO) {
-          hasNonProto2Imports = true;
-          warnNonProto2ImportFoundIn(anImport);
+        if (hasKnownSyntax == HasKnownSyntax.NO) {
+          hasUnsupportedImports = true;
+          warnUnsupportedImportFoundIn(anImport);
         }
         continue;
       }
-      if (!protobufs.isProto2(importedRoot)) {
-        alreadyChecked.put(importedRoot, IsProto2.NO);
-        hasNonProto2Imports = true;
-        warnNonProto2ImportFoundIn(anImport);
+      if (!protobufs.hasKnownSyntax(importedRoot)) {
+        alreadyChecked.put(importedRoot, HasKnownSyntax.NO);
+        hasUnsupportedImports = true;
+        warnUnsupportedImportFoundIn(anImport);
         continue;
       }
       // we have a circular dependency
       if (currentlyChecking.contains(importedRoot)) {
         continue;
       }
-      // this is a proto2 file. Need to check its imports.
+      // this is a supported file. Need to check its imports.
       importsToCheck.add(pair(anImport, importedRoot));
     }
     for (Pair<Import, Protobuf> importToCheck : importsToCheck) {
-      if (hasNonProto2Imports(importToCheck.getSecond(), currentlyChecking, alreadyChecked)) {
-        hasNonProto2Imports = true;
-        warnNonProto2ImportFoundIn(importToCheck.getFirst());
+      if (hasUnknownSyntaxImports(importToCheck.getSecond(), currentlyChecking, alreadyChecked)) {
+        hasUnsupportedImports = true;
+        warnUnsupportedImportFoundIn(importToCheck.getFirst());
       }
     }
-    isProto2 = hasNonProto2Imports ? IsProto2.NO : IsProto2.YES;
-    alreadyChecked.put(root, isProto2);
+    hasKnownSyntax = hasUnsupportedImports ? HasKnownSyntax.NO : HasKnownSyntax.YES;
+    alreadyChecked.put(root, hasKnownSyntax);
     currentlyChecking.remove(root);
-    return hasNonProto2Imports;
+    return hasUnsupportedImports;
   }
 
-  private void warnNonProto2ImportFoundIn(Import anImport) {
-    warning(importingNonProto2, anImport, IMPORT__IMPORT_URI, INSIGNIFICANT_INDEX);
+  private void warnUnsupportedImportFoundIn(Import anImport) {
+    warning(importingUnsupportedSyntax, anImport, IMPORT__IMPORT_URI, INSIGNIFICANT_INDEX);
   }
 
   /**
-   * Verifies that the URI of the given {@code Import} has been resolved. If the URI has not been resolved, this
-   * validator will create an error marker for the given {@code Import}.
+   * Verifies that the URI of the given {@code Import} has been resolved. If the URI has not been
+   * resolved, this validator will create an error marker for the given {@code Import}.
+   *
    * @param anImport the given {@code Import}.
    */
   @Check public void checkUriIsResolved(Import anImport) {
@@ -131,7 +134,7 @@
     }
   }
 
-  private static enum IsProto2 {
+  private static enum HasKnownSyntax {
     YES, NO;
   }
 }
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 abfff65..66eee36 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
@@ -25,13 +25,13 @@
   public static String expectedTrueOrFalse;
   public static String fieldNumberAlreadyUsed;
   public static String fieldNumbersMustBePositive;
-  public static String importingNonProto2;
+  public static String importingUnsupportedSyntax;
   public static String importNotFound;
   public static String literalNotInEnum;
   public static String missingFieldNumber;
   public static String multiplePackages;
-  public static String nonProto2;
   public static String scopingError;
+  public static String unknownSyntax;
   public static String unrecognizedSyntaxIdentifier;
 
   static {
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 105a56a..38bccda 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
@@ -9,11 +9,11 @@
 expectedTrueOrFalse = Expected "true" or "false".
 fieldNumberAlreadyUsed = Field number %d has already been used in \"%s\" by field \"%s\".
 fieldNumbersMustBePositive = Field numbers must be positive integers.
-importingNonProto2 = Importing non-proto2 file (directly or indirectly.) This may cause errors related to unresolved references.
+importingUnsupportedSyntax = Importing unsupported file (directly or indirectly.) This may cause errors related to unresolved references.
 importNotFound = Import \"%s\" was not found.
 literalNotInEnum = Enum type \"%s\" has no value named \"%s\".
 missingFieldNumber = Missing field number.
 multiplePackages = Multiple package definitions.
-nonProto2 = Deprecated syntax.  This parser only recognizes \"proto2\".
 scopingError = It may be caused by an imported non-proto2 file.
-unrecognizedSyntaxIdentifier = Unrecognized syntax identifier \"%s\".  This parser only recognizes \"proto2\".
+unknownSyntax = Unknown syntax.  This parser only recognizes \"proto2\" or \"proto3\".
+unrecognizedSyntaxIdentifier = Unrecognized syntax identifier \"%s\".  This parser only recognizes \"proto2\" and \"proto3\".
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
index 38bc64e..9bc3f57 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
@@ -17,7 +17,7 @@
 import static com.google.eclipse.protobuf.validation.Messages.fieldNumberAlreadyUsed;
 import static com.google.eclipse.protobuf.validation.Messages.fieldNumbersMustBePositive;
 import static com.google.eclipse.protobuf.validation.Messages.multiplePackages;
-import static com.google.eclipse.protobuf.validation.Messages.nonProto2;
+import static com.google.eclipse.protobuf.validation.Messages.unknownSyntax;
 import static com.google.eclipse.protobuf.validation.Messages.unrecognizedSyntaxIdentifier;
 
 import org.eclipse.emf.ecore.EObject;
@@ -45,7 +45,7 @@
  */
 @ComposedChecks(validators = { DataTypeValidator.class, ImportValidator.class })
 public class ProtobufJavaValidator extends AbstractProtobufJavaValidator {
-  public static final String SYNTAX_IS_NOT_PROTO2_ERROR = "syntaxIsNotProto2";
+  public static final String SYNTAX_IS_NOT_KNOWN_ERROR = "syntaxIsNotProto2";
   public static final String INVALID_FIELD_TAG_NUMBER_ERROR = "invalidFieldTagNumber";
   public static final String MORE_THAN_ONE_PACKAGE_ERROR = "moreThanOnePackage";
 
@@ -54,19 +54,19 @@
   @Inject private Protobufs protobufs;
   @Inject private IQualifiedNameProvider qualifiedNameProvider;
 
-  @Check public void checkIsProto2(Protobuf protobuf) {
-    if (!protobufs.isProto2(protobuf)) {
-      warning(nonProto2, null);
+  @Check public void checkIsKnownSyntax(Protobuf protobuf) {
+    if (!protobufs.hasKnownSyntax(protobuf)) {
+      warning(unknownSyntax, null);
     }
   }
 
-  @Check public void checkSyntaxIsProto2(Syntax syntax) {
+  @Check public void checkSyntaxIsKnown(Syntax syntax) {
     String name = syntax.getName();
-    if (Syntaxes.proto2().equals(name)) {
+    if (Syntaxes.proto2().equals(name) || Syntaxes.proto3().equals(name)) {
       return;
     }
     String msg = (name == null) ? expectedSyntaxIdentifier : format(unrecognizedSyntaxIdentifier, name);
-    error(msg, syntax, SYNTAX__NAME, SYNTAX_IS_NOT_PROTO2_ERROR);
+    error(msg, syntax, SYNTAX__NAME, SYNTAX_IS_NOT_KNOWN_ERROR);
   }
 
   @Check public void checkTagNumberIsUnique(IndexedElement e) {
@@ -81,17 +81,17 @@
     if (container instanceof Message) {
       Message message = (Message) container;
       Iterable<MessageElement> elements = message.getElements();
-      checkTagNumerIsUnique(e, message, elements);
+      checkTagNumberIsUnique(e, message, elements);
     }
   }
 
-  private boolean checkTagNumerIsUnique(IndexedElement e, EObject message, 
+  private boolean checkTagNumberIsUnique(IndexedElement e, EObject message, 
       Iterable<MessageElement> elements) {
     long index = indexedElements.indexOf(e);
 
     for (MessageElement element : elements) {
       if (element instanceof OneOf) {
-        if (!checkTagNumerIsUnique(e, message, ((OneOf) element).getElements())) {
+        if (!checkTagNumberIsUnique(e, message, ((OneOf) element).getElements())) {
           return false;
         }
       } else if (element instanceof IndexedElement) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufResourceValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufResourceValidator.java
index 4fa2ce3..a33d0ec 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufResourceValidator.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufResourceValidator.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.collect.Lists.newArrayListWithExpectedSize;
 import static com.google.common.collect.Maps.newHashMap;
-import static com.google.eclipse.protobuf.validation.Messages.importingNonProto2;
+import static com.google.eclipse.protobuf.validation.Messages.importingUnsupportedSyntax;
 import static com.google.eclipse.protobuf.validation.Messages.scopingError;
 
 import java.util.List;
@@ -110,7 +110,7 @@
       return hasNonProto2Import;
     }
     for (Diagnostic child : diagnostic.getChildren()) {
-      if (importingNonProto2.equals(child.getMessage())) {
+      if (importingUnsupportedSyntax.equals(child.getMessage())) {
         hasNonProto2Import = Status.PROTO1_IMPORTS_FOUND;
       }
       issueFromEValidatorDiagnostic(child, acceptor);