In progress: [Issue 155] Editor does not support complex custom options.
Working on content assist.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionExtendMessageFieldSource_optionExtendMessageField_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionExtendMessageFieldSource_optionExtendMessageField_Test.java
index 101bac3..1e90c24 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionExtendMessageFieldSource_optionExtendMessageField_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionExtendMessageFieldSource_optionExtendMessageField_Test.java
@@ -54,7 +54,7 @@
// }
//
// extend Type {
- // optional boolean active = 10;
+ // optional bool active = 10;
// }
//
// extend google.protobuf.FileOptions {
@@ -80,7 +80,7 @@
// }
//
// extend Type {
- // optional boolean active = 10;
+ // optional bool active = 10;
// }
//
// extend google.protobuf.FieldOptions {
@@ -88,7 +88,7 @@
// }
//
// message Person {
- // optional boolean active = 1 [(type).(active) = true];
+ // optional bool active = 1 [(type).(active) = true];
// }
@Test public void should_provide_message_fields_for_first_field_in_field_custom_option() {
CustomFieldOption option = xtext.find("type", ")", CustomFieldOption.class);
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 8923b87..87cae0d 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
@@ -15,6 +15,7 @@
import static java.lang.String.valueOf;
import static java.util.Collections.emptyList;
import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
+import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.findActualSemanticObjectFor;
import static org.eclipse.xtext.util.Strings.toFirstLower;
import java.util.*;
@@ -24,7 +25,8 @@
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Image;
import org.eclipse.xtext.*;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.ui.PluginImageHelper;
@@ -49,7 +51,6 @@
public class ProtobufProposalProvider extends AbstractProtobufProposalProvider {
@Inject private IEObjectDescriptionChooser descriptionChooser;
- @Inject private ProtobufScopeProvider scopes;
@Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private FieldOptions fieldOptions;
@Inject private ModelFinder finder;
@@ -59,7 +60,7 @@
@Inject private Literals literals;
@Inject private Options options;
@Inject private Properties properties;
-
+
@Override public void completeProtobuf_Syntax(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {}
@@ -73,7 +74,7 @@
String proposal = SYNTAX + space() + EQUAL_PROTO2_IN_QUOTES;
proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor);
}
-
+
@Override public void completeNativeOption_Source(EObject model, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
@@ -161,7 +162,7 @@
Property p = propertyFrom(context);
return p != null && properties.mayBeNan(p);
}
-
+
private Property propertyFrom(ContentAssistContext context) {
EObject model = context.getCurrentModel();
if (model instanceof Property) return (Property) model;
@@ -372,7 +373,7 @@
}
return false;
}
-
+
private void proposeBooleanValues(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
CommonKeyword[] keywords = { FALSE, TRUE };
proposeAndAccept(keywords, context, acceptor);
@@ -403,15 +404,11 @@
return word.equals(previousWord);
}
- @Override public void completeOptionSource_OptionField(EObject model, Assignment assignment,
- ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- }
-
@Override public void completeCustomOption_Source(EObject model, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
if (!(model instanceof CustomOption)) return;
CustomOption option = (CustomOption) model;
- IScope scope = scopes.scope_OptionSource_optionField(option.getSource(), null);
+ IScope scope = getScopeProvider().scope_OptionSource_optionField(option.getSource(), null);
proposeAndAcceptOptions(scope, context, acceptor);
}
@@ -419,21 +416,67 @@
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
if (!(model instanceof CustomFieldOption)) return;
CustomFieldOption option = (CustomFieldOption) model;
- IScope scope = scopes.scope_OptionSource_optionField(option.getSource(), null);
+ IScope scope = getScopeProvider().scope_OptionSource_optionField(option.getSource(), null);
proposeAndAcceptOptions(scope, context, acceptor);
}
-
+
private void proposeAndAcceptOptions(IScope scope, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
Image image = imageForOption();
for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) {
proposeAndAccept(d, image, context, acceptor);
}
}
-
+
private Image imageForOption() {
return imageHelper.getImage(images.imageFor(Option.class));
}
+ @Override public void completeCustomOption_OptionFields(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ }
+
+ @Override public void completeCustomFieldOption_OptionFields(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ }
+
+ @Override public void completeOptionSource_OptionField(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ }
+
+ @Override public void completeOptionMessageFieldSource_OptionMessageField(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ }
+
+ @Override public void completeOptionExtendMessageFieldSource_OptionExtendMessageField(EObject model,
+ Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ }
+
+ @Override public void complete_OptionMessageFieldSource(EObject model, RuleCall ruleCall,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ INode node = context.getCurrentNode();
+ EObject e = findActualSemanticObjectFor(node);
+ if (!(e instanceof OptionMessageFieldSource)) return;
+ OptionMessageFieldSource s = (OptionMessageFieldSource) e;
+ IScope scope = getScopeProvider().scope_OptionMessageFieldSource_optionMessageField(s, null);
+ for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) {
+ Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy()));
+ proposeAndAccept(d, image, context, acceptor);
+ }
+ }
+
+ @Override public void complete_OptionExtendMessageFieldSource(EObject model, RuleCall ruleCall,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ INode node = context.getCurrentNode();
+ EObject e = findActualSemanticObjectFor(node);
+ if (!(e instanceof OptionExtendMessageFieldSource)) return;
+ OptionExtendMessageFieldSource s = (OptionExtendMessageFieldSource) e;
+ IScope scope = getScopeProvider().scope_OptionExtendMessageFieldSource_optionExtendMessageField(s, null);
+ for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) {
+ Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy()));
+ proposeAndAccept(d, image, context, acceptor);
+ }
+ }
+
private void proposeAndAccept(IEObjectDescription d, Image image, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
QualifiedName name = d.getName();
@@ -441,41 +484,6 @@
ICompletionProposal proposal = createCompletionProposal(name.toString(), display, image, context);
acceptor.accept(proposal);
}
-
- @Override public void completeCustomOption_OptionFields(EObject model, Assignment assignment,
- ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- super.completeCustomOption_OptionFields(model, assignment, context, acceptor);
- }
-
- @Override public void completeCustomFieldOption_OptionFields(EObject model, Assignment assignment,
- ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- super.completeCustomFieldOption_OptionFields(model, assignment, context, acceptor);
- }
-
-
-// @Override public void completeCustomOption_PropertyField(EObject model, Assignment assignment,
-// ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-// if (!(model instanceof CustomOption)) return;
-// Property property = options.propertyFrom((CustomOption) model);
-// proposeAndAcceptOptionFields(property, context, acceptor);
-// }
-//
-// @Override public void completeCustomFieldOption_PropertyField(EObject model, Assignment assignment,
-// ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-// if (!(model instanceof CustomFieldOption)) return;
-// Property property = fieldOptions.propertyFrom((CustomFieldOption) model);
-// proposeAndAcceptOptionFields(property, context, acceptor);
-// }
-
- private void proposeAndAcceptOptionFields(Property property, ContentAssistContext context,
- ICompletionProposalAcceptor acceptor) {
- Message message = finder.messageTypeOf(property);
- if (message == null) return;
- Image image = imageHelper.getImage("property.gif");
- for (Property p : finder.propertiesOf(message)) {
- proposeAndAccept(p.getName(), image, context, acceptor);
- }
- }
@Override public void completeCustomOption_Value(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
@@ -487,7 +495,7 @@
proposeAndAcceptOptionFieldValue((Property) f, context, acceptor);
}
}
-
+
@Override public void completeCustomFieldOption_Value(EObject model, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// TODO content assist returns "{"
@@ -509,10 +517,14 @@
proposeAndAccept(enumType, context, acceptor);
}
}
-
+
private void proposeAndAccept(String proposalText, Image image, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
ICompletionProposal proposal = createCompletionProposal(proposalText, proposalText, image, context);
acceptor.accept(proposal);
}
+
+ @Override public ProtobufScopeProvider getScopeProvider() {
+ return (ProtobufScopeProvider) super.getScopeProvider();
+ }
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
index b6a5b02..b2e9973 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
@@ -8,21 +8,21 @@
*/
package com.google.eclipse.protobuf.scoping;
-import static java.util.Collections.emptyList;
+import static java.util.Collections.*;
import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
-import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.parser.NonProto2;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.Inject;
+import java.util.*;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.*;
import org.eclipse.xtext.resource.IEObjectDescription;
-import java.util.*;
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.parser.NonProto2;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
/**
* @author alruiz@google.com (Alex Ruiz)
@@ -45,7 +45,7 @@
descriptions.addAll(imported(root, scopeFinder, criteria));
return descriptions;
}
-
+
Collection<IEObjectDescription> traverseAst(Protobuf start, ScopeFinder scopeFinder, Object criteria) {
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
descriptions.addAll(local(start, scopeFinder, criteria));
@@ -58,7 +58,7 @@
}
private Collection<IEObjectDescription> local(EObject start, ScopeFinder scopeFinder, Object criteria, int level) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
for (EObject element : start.eContents()) {
descriptions.addAll(scopeFinder.descriptions(element, criteria, level));
if (element instanceof Message) {
@@ -71,13 +71,15 @@
private Collection<IEObjectDescription> imported(Protobuf start, ScopeFinder scopeFinder, Object criteria) {
List<Import> allImports = modelFinder.importsIn(start);
if (allImports.isEmpty()) return emptyList();
- ResourceSet resourceSet = start.eResource().getResourceSet();
+ Resource resource = start.eResource();
+ if (resource == null) return emptySet();
+ ResourceSet resourceSet = resource.getResourceSet();
return imported(allImports, modelFinder.packageOf(start), resourceSet, scopeFinder, criteria);
}
private Collection<IEObjectDescription> imported(List<Import> allImports, Package aPackage,
ResourceSet resourceSet, ScopeFinder scopeFinder, Object criteria) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
for (Import anImport : allImports) {
if (imports.isImportingDescriptor(anImport)) {
descriptions.addAll(scopeFinder.fromProtoDescriptor(anImport, criteria));
@@ -111,7 +113,7 @@
}
private Collection<IEObjectDescription> local(Resource resource, ScopeFinder scopeFinder, Object criteria) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
TreeIterator<Object> contents = getAllContents(resource, true);
while (contents.hasNext()) {
Object next = contents.next();