Skip to content

Commit 5c7f38c

Browse files
#71: Support proto3 extensions
While proto3 replaces regular extensions with Any, custom options are a valid use for the extension mechanism.
1 parent a7539fc commit 5c7f38c

File tree

7 files changed

+76
-7
lines changed

7 files changed

+76
-7
lines changed

src/main/java/io/protostuff/jetbrains/plugin/annotator/ProtoErrorsAnnotator.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static io.protostuff.jetbrains.plugin.ProtostuffBundle.message;
44

55
import com.google.common.annotations.VisibleForTesting;
6+
import com.google.common.collect.ImmutableSet;
67
import com.intellij.codeInspection.ProblemHighlightType;
78
import com.intellij.lang.ASTNode;
89
import com.intellij.lang.annotation.Annotation;
@@ -11,6 +12,7 @@
1112
import com.intellij.psi.PsiElement;
1213
import com.intellij.psi.PsiReference;
1314
import io.protostuff.compiler.model.Field;
15+
import io.protostuff.compiler.model.ProtobufConstants;
1416
import io.protostuff.jetbrains.plugin.psi.AntlrParserRuleNode;
1517
import io.protostuff.jetbrains.plugin.psi.EnumConstantNode;
1618
import io.protostuff.jetbrains.plugin.psi.EnumNode;
@@ -54,6 +56,16 @@ public class ProtoErrorsAnnotator implements Annotator {
5456
private static final int SYS_RESERVED_START = 19000;
5557
private static final int SYS_RESERVED_END = 19999;
5658

59+
private static final Set<String> VALID_PROTO3_EXTENDEES = ImmutableSet.of(
60+
ProtobufConstants.MSG_ENUM_OPTIONS,
61+
ProtobufConstants.MSG_ENUM_VALUE_OPTIONS,
62+
ProtobufConstants.MSG_FIELD_OPTIONS,
63+
ProtobufConstants.MSG_FILE_OPTIONS,
64+
ProtobufConstants.MSG_MESSAGE_OPTIONS,
65+
ProtobufConstants.MSG_METHOD_OPTIONS,
66+
ProtobufConstants.MSG_ONEOF_OPTIONS,
67+
ProtobufConstants.MSG_SERVICE_OPTIONS
68+
);
5769
private AnnotationHolder holder;
5870

5971
@Override
@@ -145,11 +157,27 @@ private void checkFirstEnumConstantValueIsZero(EnumNode anEnum, List<EnumConstan
145157
}
146158

147159
private void checkExtendNodeDeprecated(ExtendNode element, Syntax syntax) {
148-
if (syntax != Syntax.PROTO3) {
160+
PsiElement extendee = null;
161+
TypeReferenceNode target = element.getTarget();
162+
if (target != null) {
163+
PsiReference reference = target.getReference();
164+
if (reference != null) {
165+
extendee = reference.resolve();
166+
}
167+
}
168+
if (!(extendee instanceof MessageNode)) {
169+
String message = message("error.extensions.not.supported");
170+
markError(element.getNode(), element.getTargetNode(), message);
149171
return;
150172
}
151-
String message = message("error.extensions.not.supported");
152-
markError(element.getNode(), null, message);
173+
if (syntax == Syntax.PROTO3) {
174+
MessageNode message = (MessageNode) extendee;
175+
String qualifiedName = message.getQualifiedName();
176+
if (!VALID_PROTO3_EXTENDEES.contains(qualifiedName)) {
177+
String text = message("error.extensions.not.supported");
178+
markError(element.getNode(), element.getTargetNode(), text);
179+
}
180+
}
153181
}
154182

155183
private void checkGroupNodeDeprecated(GroupNode element, Syntax syntax) {

src/main/java/io/protostuff/jetbrains/plugin/psi/ExtendNode.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ public TypeReferenceNode getTarget() {
2222
return findChildByClass(TypeReferenceNode.class);
2323
}
2424

25+
/**
26+
* Returns extendee name node, if it exists.
27+
*/
28+
public ASTNode getTargetNode() {
29+
TypeReferenceNode target = getTarget();
30+
if (target != null) {
31+
return target.getNode();
32+
}
33+
return null;
34+
}
35+
2536
/**
2637
* Returns namespace for fields of this extension.
2738
*/

src/main/resources/io/protostuff/protobuf-jetbrains-plugin/messages/ProtostuffBundle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ error.missing.field.label=Missing field label
2525
error.illegal.field.label=Field label "{0}" is not allowed in proto3
2626
error.default.value.not.supported=Default values are not supported in proto3
2727
error.groups.not.supported=Groups are not supported in proto3
28-
error.extensions.not.supported=Extensions are not supported in proto3
28+
error.extensions.not.supported=Cannot extend given type
2929
error.first.enum.value.should.be.zero=First enum value must be zero in proto3
3030
error.illegal.oneof.field.label=Oneof field cannot have label
3131
error.unresolved.reference=Unresolved reference

src/test/java/io/protostuff/jetbrains/plugin/annotator/ProtoErrorsAnnotatorTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ public void testProto3IllegalGroup() {
9494
check();
9595
}
9696

97+
public void testProto3ValidExtend() {
98+
check();
99+
}
100+
101+
public void testProto2IllegalExtend() {
102+
check();
103+
}
104+
97105
public void testProto3IllegalExtend() {
98106
check();
99107
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
syntax = "proto2";
2+
3+
package annotator;
4+
5+
enum RegularEnum {
6+
7+
}
8+
9+
extend <error descr="Cannot extend given type">RegularEnum</error> {
10+
11+
}

src/test/resources/annotator/Proto3IllegalExtend.proto

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ syntax = "proto3";
22

33
package annotator;
44

5-
import "google/protobuf/descriptor.proto";
5+
message RegularMessage {
66

7-
<error descr="Extensions are not supported in proto3">extend google.protobuf.MessageOptions {
7+
}
88

9-
}</error>
9+
extend <error descr="Cannot extend given type">RegularMessage</error> {
10+
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
syntax = "proto3";
2+
3+
package annotator;
4+
5+
import "google/protobuf/descriptor.proto";
6+
7+
extend google.protobuf.MessageOptions {
8+
9+
}

0 commit comments

Comments
 (0)