Fixed: [ Issue 56 ] Keywords are valid element names
https://code.google.com/p/protobuf-dt/issues/detail?id=56
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
index 9f6c7ab..380ffc4 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
@@ -15,19 +15,19 @@
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.xtext.ui.LanguageSpecific;
-import org.eclipse.xtext.ui.editor.IURIEditorOpener;
-import org.eclipse.xtext.ui.editor.IXtextEditorCallback;
+import org.eclipse.xtext.ui.editor.*;
import org.eclipse.xtext.ui.editor.model.XtextDocumentProvider;
import org.eclipse.xtext.ui.editor.outline.actions.IOutlineContribution;
import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreInitializer;
+import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;
import com.google.eclipse.protobuf.scoping.IFileUriResolver;
import com.google.eclipse.protobuf.ui.builder.AutoAddNatureEditorCallback;
import com.google.eclipse.protobuf.ui.editor.ProtobufUriEditorOpener;
import com.google.eclipse.protobuf.ui.editor.hyperlinking.ProtobufHyperlinkDetector;
import com.google.eclipse.protobuf.ui.editor.model.ProtobufDocumentProvider;
-import com.google.eclipse.protobuf.ui.outline.LinkWithEditor;
-import com.google.eclipse.protobuf.ui.outline.ProtobufOutlinePage;
+import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.ProtobufSemanticHighlightingCalculator;
+import com.google.eclipse.protobuf.ui.outline.*;
import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferenceStoreInitializer;
import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferenceStoreInitializer;
import com.google.eclipse.protobuf.ui.scoping.FileUriResolver;
@@ -92,4 +92,8 @@
.annotatedWith(LanguageSpecific.class)
.to(ProtobufUriEditorOpener.class);
}
+
+ public void configureSemanticHighlightingCalculator(Binder binder) {
+ binder.bind(ISemanticHighlightingCalculator.class).to(ProtobufSemanticHighlightingCalculator.class);
+ }
}
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
new file mode 100644
index 0000000..5a730de
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
@@ -0,0 +1,122 @@
+/*
+ * Created on Jun 2, 2011
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright @2011 the original author or authors.
+ */
+package com.google.eclipse.protobuf.ui.editor.syntaxcoloring;
+
+import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature;
+import static org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration.DEFAULT_ID;
+
+import java.util.List;
+
+import org.eclipse.emf.ecore.*;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.ui.editor.syntaxcoloring.*;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
+
+ public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
+ if (resource.getContents().isEmpty()) return;
+ Protobuf protobuf = (Protobuf) resource.getContents().get(0);
+ highlightAllNames(protobuf, acceptor, DEFAULT_ID);
+ }
+
+ 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 Type) {
+ highlightName(element, acceptor, highlightId);
+ if (element instanceof Message) highlightElementNames((Message) element, acceptor, highlightId);
+ continue;
+ }
+ if (element instanceof Service) {
+ highlightName(element, acceptor, highlightId);
+ highlightRpcNames((Service) element, acceptor, highlightId);
+ }
+ }
+ }
+
+ private void highlightElementNames(Message message, IHighlightedPositionAcceptor acceptor, String highlightId) {
+ for (MessageElement element : message.getElements()) {
+ if (element instanceof Option) {
+ highlightName(element, acceptor, highlightId);
+ continue;
+ }
+ if (element instanceof Field) {
+ highlightName(element, acceptor, highlightId);
+ highLightFieldOptionNames((Field) element, acceptor, highlightId);
+ }
+ if (element instanceof Group) {
+ for (Property property : ((Group) element).getElements()) {
+ highlightName(property, acceptor, highlightId);
+ highLightFieldOptionNames(property, acceptor, highlightId);
+ }
+ }
+ }
+ }
+
+ private void highLightFieldOptionNames(Field field, IHighlightedPositionAcceptor acceptor, String highlightId) {
+ for (FieldOption option : field.getFieldOptions()) {
+ highlightName(option, acceptor, highlightId);
+ }
+ }
+
+ private void highlightRpcNames(Service service, IHighlightedPositionAcceptor acceptor, String highlightId) {
+ for (Rpc rpc : service.getRpcs()) {
+ highlightName(rpc, acceptor, highlightId);
+ for (Option option : rpc.getOptions()) {
+ highlightName(option, acceptor, highlightId);
+ }
+ }
+ }
+
+ private void highlightName(EObject o, IHighlightedPositionAcceptor acceptor, String highlightId) {
+ highlightFirstFeature(o, o.eClass().getEStructuralFeature("name"), highlightId, acceptor);
+ }
+
+ private void highlightFirstFeature(EObject semantic, EStructuralFeature feature, String highlightId,
+ IHighlightedPositionAcceptor acceptor) {
+ INode node = firstFeatureNode(semantic, feature);
+ if (node == null || node.getText() == null) return;
+ acceptor.addPosition(node.getOffset(), node.getText().length(), highlightId);
+ }
+
+ public INode firstFeatureNode(EObject semantic, EStructuralFeature feature) {
+ List<INode> nodes = findNodesForFeature(semantic, feature);
+ return (nodes.size() == 1) ? nodes.get(0) : null;
+ }
+}
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 9926ea1..303bc4a 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
@@ -29,10 +29,10 @@
'import' importURI=STRING ';';
QualifiedName:
- ID ('.' ID)*;
+ Name ('.' Name)*;
Option:
- 'option' name=ID '=' value=ValueRef ';';
+ 'option' name=Name '=' value=ValueRef ';';
ProtobufElement:
Type | ExtendMessage | Service;
@@ -41,7 +41,7 @@
Message | Enum;
Message:
- 'message' name=ID '{'
+ 'message' name=Name '{'
elements+=MessageElement*
('extensions' extensionsFrom=INT 'to' (extensionsTo=INT | 'max') ';')?
'}'(';')?;
@@ -53,13 +53,13 @@
Property | Group;
Group:
- modifier=Modifier 'group' name=ID '=' index=INT
+ modifier=Modifier 'group' name=Name '=' index=INT
('[' (fieldOptions+=FieldOption (',' fieldOptions+=FieldOption)*) ']')? '{'
elements+=Property*
'}'(';')?;
Property:
- modifier=Modifier type=AbstractTypeReference name=(ID | 'message') '=' index=INT
+ modifier=Modifier type=AbstractTypeReference name=Name '=' index=INT
(
('[' 'default' '=' default=ValueRef ']') |
('[' 'default' '=' default=ValueRef (',' fieldOptions+=FieldOption)* ']') |
@@ -67,7 +67,7 @@
)? ';';
FieldOption:
- name=ID '=' value=ValueRef;
+ name=Name '=' value=ValueRef;
enum Modifier:
required
@@ -127,12 +127,12 @@
string=STRING;
Enum:
- 'enum' name=ID '{'
+ 'enum' name=Name '{'
literals+=Literal*
'}' ';'?;
Literal:
- name=ID '=' index=INT ';';
+ name=Name '=' index=INT ';';
ExtendMessage:
'extend' message=MessageReference '{'
@@ -140,15 +140,19 @@
'}'(';')?;
Service:
- 'service' name=ID '{'
+ 'service' name=Name '{'
rpcs+=Rpc*
'}';
Rpc:
- 'rpc' name=ID '(' argType=MessageReference ')' 'returns' '(' returnType=MessageReference ')'
+ 'rpc' name=Name '(' argType=MessageReference ')' 'returns' '(' returnType=MessageReference ')'
(('{' options+=Option* '}')(';')? | ';')
;
+Name:
+ ID | 'package' | 'import' | 'option' | 'extend' | 'message' | 'optional' | 'required' | 'repeated' | 'group' | 'enum'
+ | 'service' | 'rpc' | 'returns' | 'true' | 'false' | 'default' | 'extensions' | 'to' | 'max';
+
MessageReference:
type=[Message | QualifiedName];