Fixed: [ Issue 58 ] protobuf-dt expects imports and options to be grouped together
https://code.google.com/p/protobuf-dt/issues/detail?id=58
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
index 31583dc..b530ec6 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
@@ -33,7 +33,7 @@
}
public static Option findOption(String name, Protobuf root) {
- for (Option option : root.getOptions())
+ for (Option option : getAllContentsOfType(root, Option.class))
if (name.equals(option.getName())) return option;
return null;
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/util/ProtobufElementFinder_importsIn_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/util/ProtobufElementFinder_importsIn_Test.java
new file mode 100644
index 0000000..bc73f66
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/util/ProtobufElementFinder_importsIn_Test.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+
+/**
+ * Tests for <code>{@link ProtobufElementFinder#importsIn(Protobuf)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufElementFinder_importsIn_Test {
+
+ @Rule public XtextRule xtext = new XtextRule();
+
+ private ProtobufElementFinder finder;
+
+ @Before public void setUp() {
+ finder = xtext.getInstanceOf(ProtobufElementFinder.class);
+ }
+
+ @Test public void should_return_all_imports() {
+ StringBuilder proto = new StringBuilder();
+ proto.append("import \"luke.proto\"")
+ .append("import \"leia.proto\"");
+ Protobuf root = xtext.parse(proto);
+ List<Import> allImports = finder.importsIn(root);
+ assertThat(allImports.size(), equalTo(2));
+ assertThat(allImports.get(0).getImportURI(), equalTo("luke.proto"));
+ assertThat(allImports.get(1).getImportURI(), equalTo("leia.proto"));
+ }
+
+ @Test public void should_return_empty_if_no_imports_found() {
+ StringBuilder proto = new StringBuilder();
+ proto.append("enum PhoneType {")
+ .append(" MOBILE = 0; ")
+ .append(" HOME = 1; ")
+ .append(" WORK = 2; ")
+ .append("} ");
+ Protobuf root = xtext.parse(proto);
+ List<Import> allImports = finder.importsIn(root);
+ assertThat(allImports.size(), equalTo(0));
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
index 5a730de..043be93 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
@@ -39,25 +39,15 @@
}
private void highlightAllNames(Protobuf protobuf, IHighlightedPositionAcceptor acceptor, String highlightId) {
- highlightPackageName(protobuf, acceptor, highlightId);
- highlightFileOptionNames(protobuf, acceptor, highlightId);
highlightElementNames(protobuf, acceptor, highlightId);
}
- private void highlightPackageName(Protobuf protobuf, IHighlightedPositionAcceptor acceptor, String highlightId) {
- Package aPackage = protobuf.getPackage();
- if (aPackage == null) return;
- highlightName(aPackage, acceptor, highlightId);
- }
-
- private void highlightFileOptionNames(Protobuf protobuf, IHighlightedPositionAcceptor acceptor, String highlightId) {
- for (Option option : protobuf.getOptions()) {
- highlightName(option, acceptor, highlightId);
- }
- }
-
private void highlightElementNames(Protobuf protobuf, IHighlightedPositionAcceptor acceptor, String highlightId) {
for (ProtobufElement element : protobuf.getElements()) {
+ if (element instanceof Package || element instanceof Option) {
+ highlightName(element, acceptor, highlightId);
+ continue;
+ }
if (element instanceof Type) {
highlightName(element, acceptor, highlightId);
if (element instanceof Message) highlightElementNames((Message) element, acceptor, highlightId);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
index a7c6603..7294426 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
@@ -8,19 +8,13 @@
*/
package com.google.eclipse.protobuf.ui.outline;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
-import static com.google.eclipse.protobuf.ui.outline.Messages.*;
-
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.ui.editor.outline.IOutlineNode;
-import org.eclipse.xtext.ui.editor.outline.impl.DefaultOutlineTreeProvider;
-import org.eclipse.xtext.ui.editor.outline.impl.DocumentRootNode;
+import org.eclipse.xtext.ui.editor.outline.impl.*;
import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Package;
/**
* Customization of the default outline structure.
@@ -30,13 +24,13 @@
public class ProtobufOutlineTreeProvider extends DefaultOutlineTreeProvider {
private static final List<Class<? extends EObject>> IGNORED_ELEMENT_TYPES = new ArrayList<Class<? extends EObject>>();
-
+
static {
IGNORED_ELEMENT_TYPES.add(BooleanRef.class);
IGNORED_ELEMENT_TYPES.add(FieldOption.class);
IGNORED_ELEMENT_TYPES.add(MessageReference.class);
}
-
+
boolean _isLeaf(Option o) {
return true;
}
@@ -46,18 +40,18 @@
}
protected void _createChildren(DocumentRootNode parentNode, Protobuf protobuf) {
- Package aPackage = protobuf.getPackage();
- if (aPackage != null) {
- createNode(parentNode, aPackage);
- }
- if (!protobuf.getImports().isEmpty()) {
- createEStructuralFeatureNode(parentNode, protobuf, PROTOBUF__IMPORTS,
- labelProvider.getImage("imports"), importDeclarations, false);
- }
- if (!protobuf.getOptions().isEmpty()) {
- createEStructuralFeatureNode(parentNode, protobuf, PROTOBUF__OPTIONS,
- labelProvider.getImage("options"), optionDeclarations, false);
- }
+// Package aPackage = protobuf.getPackage();
+// if (aPackage != null) {
+// createNode(parentNode, aPackage);
+// }
+// if (!protobuf.getImports().isEmpty()) {
+// createEStructuralFeatureNode(parentNode, protobuf, PROTOBUF__IMPORTS,
+// labelProvider.getImage("imports"), importDeclarations, false);
+// }
+// if (!protobuf.getOptions().isEmpty()) {
+// createEStructuralFeatureNode(parentNode, protobuf, PROTOBUF__OPTIONS,
+// labelProvider.getImage("options"), optionDeclarations, false);
+// }
for (ProtobufElement e : protobuf.getElements()) {
createNode(parentNode, e);
}
@@ -67,7 +61,7 @@
if (isIgnored(modelElement)) return;
super.createNode(parent, modelElement);
}
-
+
private boolean isIgnored(EObject modelElement) {
for (Class<? extends EObject> ignoredType : IGNORED_ELEMENT_TYPES)
if (ignoredType.isInstance(modelElement)) return true;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
index 303bc4a..d27a97b 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
@@ -16,11 +16,13 @@
Protobuf:
(syntax=Syntax)?
- ((package=Package)? & (imports+=Import)* & (options+=Option)*)
(elements+=ProtobufElement)*;
Syntax:
'syntax' '=' name=STRING ';';
+
+ProtobufElement:
+ Package | Import | Option | Type | ExtendMessage | Service;
Package:
'package' name=QualifiedName ';';
@@ -34,9 +36,6 @@
Option:
'option' name=Name '=' value=ValueRef ';';
-ProtobufElement:
- Type | ExtendMessage | Service;
-
Type:
Message | Enum;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
index f4a09d7..0798fb2 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
@@ -14,14 +14,10 @@
import java.util.*;
-import org.eclipse.emf.common.util.TreeIterator;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.xtext.naming.IQualifiedNameProvider;
-import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.emf.common.util.*;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.resource.*;
+import org.eclipse.xtext.naming.*;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.*;
@@ -99,7 +95,7 @@
private <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
ResourceSet resourceSet = root.eResource().getResourceSet();
List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (Import anImport : root.getImports()) {
+ for (Import anImport : finder.importsIn(root)) {
URI importUri = createURI(uriResolver.apply(anImport));
Resource imported = resourceSet.getResource(importUri, true);
descriptions.addAll(innerTypes(imported, targetType));
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/ProtobufElementFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/ProtobufElementFinder.java
index 952cdf0..571f197 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/ProtobufElementFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/ProtobufElementFinder.java
@@ -8,6 +8,10 @@
*/
package com.google.eclipse.protobuf.util;
+import static java.util.Collections.unmodifiableList;
+
+import java.util.*;
+
import org.eclipse.emf.ecore.EObject;
import com.google.eclipse.protobuf.protobuf.*;
@@ -56,17 +60,34 @@
* package.
*/
public Package packageOf(EObject o) {
- return rootOf(o).getPackage();
+ Protobuf root = rootOf(o);
+ for (ProtobufElement e : root.getElements()) {
+ if (e instanceof Package) return (Package) e;
+ }
+ return null;
}
/**
- * Returns the root element of the proto file containing the given object.
- * @param o the given object.
- * @return the root element of the proto file containing the given object.
+ * Returns the root element of the proto file containing the given element.
+ * @param o the given element.
+ * @return the root element of the proto file containing the given element.
*/
public Protobuf rootOf(EObject o) {
EObject current = o;
while (!(current instanceof Protobuf)) current = current.eContainer();
return (Protobuf) current;
}
+
+ /**
+ * Returns all the import definitions in the given proto.
+ * @param root the given proto.
+ * @return all the import definitions in the given proto.
+ */
+ public List<Import> importsIn(Protobuf root) {
+ List<Import> imports = new ArrayList<Import>();
+ for (ProtobufElement e : root.getElements()) {
+ if (e instanceof Import) imports.add((Import) e);
+ }
+ return unmodifiableList(imports);
+ }
}
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 93dee55..cbd6fa0 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
@@ -22,6 +22,7 @@
public static String fieldNumbersMustBePositive;
public static String importNotFound;
public static String missingFieldNumber;
+ public static String multiplePackages;
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 4cf6b11..dbb5a26 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
@@ -5,4 +5,5 @@
fieldNumbersMustBePositive = Field numbers must be positive integers.
importNotFound = Import \"%s\" was not found.
missingFieldNumber = Missing field number.
+multiplePackages = Multiple package definitions.
unrecognizedSyntaxIdentifier = Unrecognized syntax identifier \"%s\". This parser only recognizes \"proto2\".
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 baca753..22a6323 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
@@ -15,11 +15,11 @@
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.naming.IQualifiedNameProvider;
-import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.naming.*;
import org.eclipse.xtext.validation.Check;
import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
import com.google.inject.Inject;
/**
@@ -73,6 +73,18 @@
error(msg, FIELD__INDEX);
}
+ @Check public void checkOnlyOnePackageDefinition(Package aPackage) {
+ boolean firstFound = false;
+ Protobuf root = (Protobuf) aPackage.eContainer();
+ for (ProtobufElement e : root.getElements()) {
+ if (e == aPackage) {
+ if (firstFound) error(multiplePackages, PACKAGE__NAME);
+ return;
+ }
+ if (e instanceof Package && !firstFound) firstFound = true;
+ }
+ }
+
private boolean isNameNull(Field field) {
return field.getName() == null;
}