Fixed: [Issue 124] Add hyperlinking to built-in options.
Clean up code.
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
new file mode 100644
index 0000000..b3d5568
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
@@ -0,0 +1,32 @@
+/*
+ * 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.scoping;
+
+import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class LiteralDescriptions {
+
+ Collection<IEObjectDescription> literalsOf(Enum anEnum) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (Literal literal : getAllContentsOfType(anEnum, Literal.class))
+ descriptions.add(create(literal.getName(), literal));
+ return descriptions;
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
index 1087f3b..e166f13 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
@@ -8,6 +8,9 @@
*/
package com.google.eclipse.protobuf.scoping;
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
enum OptionType {
FILE, MESSAGE, FIELD, ENUM;
}
\ No newline at end of file
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 9a705a0..e42c07a 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
@@ -8,26 +8,17 @@
*/
package com.google.eclipse.protobuf.scoping;
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addLeadingDot;
-import static java.util.Collections.emptyList;
-import static org.eclipse.emf.common.util.URI.createURI;
-import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
-import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
import static org.eclipse.xtext.resource.EObjectDescription.create;
import java.util.*;
-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.*;
+import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.*;
import com.google.eclipse.protobuf.protobuf.*;
import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.eclipse.protobuf.protobuf.Package;
import com.google.eclipse.protobuf.util.*;
import com.google.inject.Inject;
@@ -45,207 +36,58 @@
@Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private FieldOptions fieldOptions;
@Inject private ProtobufElementFinder finder;
- @Inject private ImportedNamesProvider importedNamesProvider;
- @Inject private LocalNamesProvider localNamesProvider;
- @Inject private IQualifiedNameProvider nameProvider;
+ @Inject private LiteralDescriptions literalDescriptions;
@Inject private Options options;
- @Inject private PackageResolver packageResolver;
- @Inject private ImportUriResolver uriResolver;
+ @Inject private TypeDescriptions typeDescriptions;
@SuppressWarnings("unused")
IScope scope_TypeRef_type(TypeRef typeRef, EReference reference) {
Protobuf root = finder.rootOf(typeRef);
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
EObject current = typeRef.eContainer().eContainer(); // get message of the property containing the TypeReference
+ Class<Type> targetType = Type.class;
while (current != null) {
- descriptions.addAll(typesIn(current));
+ descriptions.addAll(typeDescriptions.localTypes(current, targetType));
current = current.eContainer();
}
- descriptions.addAll(importedTypes(root, Type.class));
+ descriptions.addAll(typeDescriptions.importedTypes(root, targetType));
return createScope(descriptions);
}
- private Collection<IEObjectDescription> typesIn(EObject root) {
- return children(root, Type.class);
- }
-
@SuppressWarnings("unused")
IScope scope_MessageRef_type(MessageRef messageRef, EReference reference) {
Protobuf root = finder.rootOf(messageRef);
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
- descriptions.addAll(messagesIn(root));
- descriptions.addAll(importedTypes(root, Message.class));
+ Class<Message> targetType = Message.class;
+ descriptions.addAll(typeDescriptions.localTypes(root, targetType));
+ descriptions.addAll(typeDescriptions.importedTypes(root, targetType));
return createScope(descriptions);
}
- private Collection<IEObjectDescription> messagesIn(Protobuf root) {
- return children(root, Message.class);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(EObject root, Class<T> targetType) {
- return children(root, targetType, 0);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(EObject root, Class<T> targetType, int level) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (EObject element : root.eContents()) {
- if (!targetType.isInstance(element)) continue;
- List<QualifiedName> names = localNamesProvider.namesOf(element);
- int nameCount = names.size();
- for (int i = level; i < nameCount; i++) {
- descriptions.add(create(names.get(i), element));
- }
- descriptions.addAll(fullyQualifiedNamesOf(element));
- // TODO investigate if groups can have messages, and if so, add those messages to the scope.
- if (element instanceof Message) {
- descriptions.addAll(children(element, targetType, level + 1));
- }
- }
- return descriptions;
- }
-
- private <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
- List<Import> allImports = finder.importsIn(root);
- if (allImports.isEmpty()) return emptyList();
- return importedTypes(allImports, finder.packageOf(root), targetType);
- }
-
- private <T extends Type> Collection<IEObjectDescription> importedTypes(List<Import> allImports, Package aPackage,
- Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (Import anImport : allImports) {
- if (isImportingDescriptor(anImport)) {
- descriptions.addAll(allBuiltInTypes(targetType));
- continue;
- }
- Resource importedResource = importedResourceFrom(anImport);
- Protobuf importedRoot = rootElementOf(importedResource);
- if (importedRoot != null) {
- descriptions.addAll(publicImportedTypes(importedRoot, targetType));
- if (arePackagesRelated(aPackage, importedRoot)) {
- descriptions.addAll(typesIn(importedRoot));
- continue;
- }
- }
- descriptions.addAll(children(importedResource, targetType));
- }
- return descriptions;
- }
-
- private boolean isImportingDescriptor(Import anImport) {
- String descriptorLocation = descriptorProvider.descriptorLocation().toString();
- return descriptorLocation.equals(anImport.getImportURI());
- }
-
- private <T extends Type> Collection<IEObjectDescription> allBuiltInTypes(Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- ProtoDescriptor descriptor = descriptorProvider.get();
- for (Type t : descriptor.allTypes()) {
- if (!targetType.isInstance(t)) continue;
- T type = targetType.cast(t);
- descriptions.addAll(fullyQualifiedNamesOf(type));
- }
- return descriptions;
- }
-
- private <T extends Type> Collection<IEObjectDescription> publicImportedTypes(Protobuf root, Class<T> targetType) {
- List<Import> allImports = finder.publicImportsIn(root);
- if (allImports.isEmpty()) return emptyList();
- return importedTypes(allImports, finder.packageOf(root), targetType);
- }
-
- private Resource importedResourceFrom(Import anImport) {
- ResourceSet resourceSet = finder.rootOf(anImport).eResource().getResourceSet();
- URI importUri = createURI(uriResolver.apply(anImport));
- try {
- return resourceSet.getResource(importUri, true);
- } catch (Throwable t) {
- return null;
- }
- }
-
- private Protobuf rootElementOf(Resource resource) {
- if (resource instanceof XtextResource) {
- EObject root = ((XtextResource) resource).getParseResult().getRootASTElement();
- return (Protobuf) root;
- }
- TreeIterator<Object> contents = getAllContents(resource, true);
- if (contents.hasNext()) {
- Object next = contents.next();
- if (next instanceof Protobuf) return (Protobuf) next;
- }
- return null;
- }
-
- private boolean arePackagesRelated(Package aPackage, EObject root) {
- Package p = finder.packageOf(root);
- return packageResolver.areRelated(aPackage, p);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(Resource resource, Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- TreeIterator<Object> contents = getAllContents(resource, true);
- while (contents.hasNext()) {
- Object next = contents.next();
- if (!targetType.isInstance(next)) continue;
- T type = targetType.cast(next);
- descriptions.addAll(fullyQualifiedNamesOf(type));
- for (QualifiedName name : importedNamesProvider.namesOf(type)) {
- descriptions.add(create(name, type));
- }
- }
- return descriptions;
- }
-
- private Collection<IEObjectDescription> fullyQualifiedNamesOf(EObject obj) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
- descriptions.add(create(fqn, obj));
- descriptions.add(create(addLeadingDot(fqn), obj));
- return descriptions;
- }
-
@SuppressWarnings("unused")
IScope scope_LiteralRef_literal(LiteralRef literalRef, EReference reference) {
EObject container = literalRef.eContainer();
+ Enum anEnum = null;
+ if (container instanceof BuiltInOption) {
+ Property p = options.propertyFrom((Option) container);
+ anEnum = descriptorProvider.get().enumTypeOf(p);
+ }
if (container instanceof Property) {
- Enum anEnum = finder.enumTypeOf((Property) container);
- if (anEnum != null) return scopeForLiterals(anEnum);
+ anEnum = finder.enumTypeOf((Property) container);
}
- Enum anEnum = enumTypeOfOption(container);
- if (anEnum != null) return scopeForLiterals(anEnum);
- return null;
- }
-
- private Enum enumTypeOfOption(EObject mayBeOption) {
- ProtoDescriptor descriptor = descriptorProvider.get();
- if (mayBeOption instanceof BuiltInOption) {
- Property property = options.propertyFrom((BuiltInOption) mayBeOption);
- return descriptor.enumTypeOf(property);
- }
- if (mayBeOption instanceof BuiltInFieldOption) {
- BuiltInFieldOption option = (BuiltInFieldOption) mayBeOption;
+ if (container instanceof BuiltInFieldOption) {
+ BuiltInFieldOption option = (BuiltInFieldOption) container;
if (fieldOptions.isDefaultValueOption(option)) {
Property property = (Property) option.eContainer();
- return finder.enumTypeOf(property);
+ anEnum = finder.enumTypeOf(property);
+ } else {
+ anEnum = descriptorProvider.get().enumTypeOf(option);
}
- return descriptor.enumTypeOf(option);
}
+ if (anEnum != null) return createScope(literalDescriptions.literalsOf(anEnum));
return null;
}
- private static IScope scopeForLiterals(Enum anEnum) {
- Collection<IEObjectDescription> descriptions = describeLiterals(anEnum);
- return createScope(descriptions);
- }
-
- private static Collection<IEObjectDescription> describeLiterals(Enum anEnum) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (Literal literal : getAllContentsOfType(anEnum, Literal.class))
- descriptions.add(create(literal.getName(), literal));
- return descriptions;
- }
-
@SuppressWarnings("unused")
IScope scope_PropertyRef_property(PropertyRef propertyRef, EReference reference) {
EObject mayBeOption = propertyRef.eContainer();
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
new file mode 100644
index 0000000..e605bb6
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
@@ -0,0 +1,166 @@
+/*
+ * 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.scoping;
+
+import static com.google.eclipse.protobuf.scoping.QualifiedNames.addLeadingDot;
+import static java.util.Collections.emptyList;
+import static org.eclipse.emf.common.util.URI.createURI;
+import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.emf.common.util.*;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.*;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.resource.*;
+import org.eclipse.xtext.scoping.impl.ImportUriResolver;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class TypeDescriptions {
+
+ @Inject private ProtoDescriptorProvider descriptorProvider;
+ @Inject private ProtobufElementFinder finder;
+ @Inject private ImportedNamesProvider importedNamesProvider;
+ @Inject private LocalNamesProvider localNamesProvider;
+ @Inject private IQualifiedNameProvider nameProvider;
+ @Inject private PackageResolver packageResolver;
+ @Inject private ImportUriResolver uriResolver;
+
+ <T extends Type> Collection<IEObjectDescription> localTypes(EObject root, Class<T> targetType) {
+ return children(root, targetType, 0);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> children(EObject root, Class<T> targetType, int level) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (EObject element : root.eContents()) {
+ if (!targetType.isInstance(element)) continue;
+ List<QualifiedName> names = localNamesProvider.namesOf(element);
+ int nameCount = names.size();
+ for (int i = level; i < nameCount; i++) {
+ descriptions.add(create(names.get(i), element));
+ }
+ descriptions.addAll(fullyQualifiedNamesOf(element));
+ // TODO investigate if groups can have messages, and if so, add those messages to the scope.
+ if (element instanceof Message) {
+ descriptions.addAll(children(element, targetType, level + 1));
+ }
+ }
+ return descriptions;
+ }
+
+ <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
+ List<Import> allImports = finder.importsIn(root);
+ if (allImports.isEmpty()) return emptyList();
+ return importedTypes(allImports, finder.packageOf(root), targetType);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> importedTypes(List<Import> allImports, Package aPackage,
+ Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (Import anImport : allImports) {
+ if (isImportingDescriptor(anImport)) {
+ descriptions.addAll(allBuiltInTypes(targetType));
+ continue;
+ }
+ Resource importedResource = importedResourceFrom(anImport);
+ Protobuf importedRoot = rootElementOf(importedResource);
+ if (importedRoot != null) {
+ descriptions.addAll(publicImportedTypes(importedRoot, targetType));
+ if (arePackagesRelated(aPackage, importedRoot)) {
+ descriptions.addAll(localTypes(importedRoot, targetType));
+ continue;
+ }
+ }
+ descriptions.addAll(children(importedResource, targetType));
+ }
+ return descriptions;
+ }
+
+ private boolean isImportingDescriptor(Import anImport) {
+ String descriptorLocation = descriptorProvider.descriptorLocation().toString();
+ return descriptorLocation.equals(anImport.getImportURI());
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> allBuiltInTypes(Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ for (Type t : descriptor.allTypes()) {
+ if (!targetType.isInstance(t)) continue;
+ T type = targetType.cast(t);
+ descriptions.addAll(fullyQualifiedNamesOf(type));
+ }
+ return descriptions;
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> publicImportedTypes(Protobuf root, Class<T> targetType) {
+ List<Import> allImports = finder.publicImportsIn(root);
+ if (allImports.isEmpty()) return emptyList();
+ return importedTypes(allImports, finder.packageOf(root), targetType);
+ }
+
+ private Resource importedResourceFrom(Import anImport) {
+ ResourceSet resourceSet = finder.rootOf(anImport).eResource().getResourceSet();
+ URI importUri = createURI(uriResolver.apply(anImport));
+ try {
+ return resourceSet.getResource(importUri, true);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ private Protobuf rootElementOf(Resource resource) {
+ if (resource instanceof XtextResource) {
+ EObject root = ((XtextResource) resource).getParseResult().getRootASTElement();
+ return (Protobuf) root;
+ }
+ TreeIterator<Object> contents = getAllContents(resource, true);
+ if (contents.hasNext()) {
+ Object next = contents.next();
+ if (next instanceof Protobuf) return (Protobuf) next;
+ }
+ return null;
+ }
+
+ private boolean arePackagesRelated(Package aPackage, EObject root) {
+ Package p = finder.packageOf(root);
+ return packageResolver.areRelated(aPackage, p);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> children(Resource resource, Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ TreeIterator<Object> contents = getAllContents(resource, true);
+ while (contents.hasNext()) {
+ Object next = contents.next();
+ if (!targetType.isInstance(next)) continue;
+ T type = targetType.cast(next);
+ descriptions.addAll(fullyQualifiedNamesOf(type));
+ for (QualifiedName name : importedNamesProvider.namesOf(type)) {
+ descriptions.add(create(name, type));
+ }
+ }
+ return descriptions;
+ }
+
+ private Collection<IEObjectDescription> fullyQualifiedNamesOf(EObject obj) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
+ descriptions.add(create(fqn, obj));
+ descriptions.add(create(addLeadingDot(fqn), obj));
+ return descriptions;
+ }
+}