When I use protostuff-parser to parse proto file, A io.protostuff.compiler.parser.ParserException raised.
I read the code and found the reason:
The io.protostuff.compiler.model.Proto.getNamespace() implements as this:
@Override
public String getNamespace() {
if (pkg == null) {
return ".";
}
return "." + pkg.getValue() + ".";
}
And the default value of pkg is protected Package pkg = Package.DEFAULT;, meanwhile the implements of getValue in Package.DEFAULT return ""(empty string).
So when use ImportImpl to parse a proto file without a "package" declared, the Message and other elements in the proto file will be registered as a fullyQualifiedName starts with double point(".."):
// io.protostuff.compiler.parser.TypeRegistratorPostProcessor
private void registerUserTypes(ProtoContext context) {
final Proto proto = context.getProto();
List<Message> messages = new ArrayList<>();
messages.addAll(proto.getMessages());
// ......
for (Message type : messages) {
type.setProto(proto);
String fullyQualifiedName = proto.getNamespace() + type.getName();
type.setFullyQualifiedName(fullyQualifiedName);
context.register(fullyQualifiedName, type);
}
// ......
}
As that, When proto file "A" which declares "package" as "aaaa.bbb", imports another proto file "B" which no "package" declared, it will not be able to found Message XXX declared in B, because the XXX is registered as "..XXX", and the look up for XXX is only for ".aaa.bbb.XXX", ".aaa.XXX", ".XXX":
// io.protostuff.compiler.parser.TypeResolverPostProcessor
public static Deque<String> createScopeLookupList(UserTypeContainer container) {
String namespace = container.getNamespace();
Deque<String> scopeLookupList = new ArrayDeque<>();
int end = 0;
while (end >= 0) {
end = namespace.indexOf('.', end);
if (end >= 0) {
end++;
String scope = namespace.substring(0, end);
scopeLookupList.addFirst(scope);
}
}
return scopeLookupList;
}
private UserType resolveUserType(Element source, ProtoContext context, Deque<String> scopeLookupList, String typeName) {
UserType fieldType = null;
// A leading '.' (for example, .foo.bar.Baz) means to start from the outermost scope
if (typeName.startsWith(".")) {
UserType type = (UserType) context.resolve(typeName);
if (type != null) {
fieldType = type;
}
} else {
for (String scope : scopeLookupList) {
String fullTypeName = scope + typeName;
UserType type = (UserType) context.resolve(fullTypeName);
if (type != null) {
fieldType = type;
break;
}
}
}
if (fieldType == null) {
String format = "Unresolved reference: '%s'";
throw new ParserException(source, format, typeName);
}
return fieldType;
}
I think it is legal to create a proto file without "package". So I wonder:
If there are a bug with proto file no "package" declared?
Is it more rational to make the pkg of Proto as null or change the implement of getNamespace to return "." when pkg == Package.DEFAULT?
When I use protostuff-parser to parse proto file, A
io.protostuff.compiler.parser.ParserException
raised. I read the code and found the reason:The io.protostuff.compiler.model.Proto.getNamespace() implements as this:
And the default value of
pkg
isprotected Package pkg = Package.DEFAULT;
, meanwhile the implements ofgetValue
in Package.DEFAULT return ""(empty string).So when use
ImportImpl
to parse a proto file without a "package" declared, the Message and other elements in the proto file will be registered as a fullyQualifiedName starts with double point(".."):As that, When proto file "A" which declares "package" as "aaaa.bbb", imports another proto file "B" which no "package" declared, it will not be able to found Message XXX declared in B, because the XXX is registered as "..XXX", and the look up for XXX is only for ".aaa.bbb.XXX", ".aaa.XXX", ".XXX":
I think it is legal to create a proto file without "package". So I wonder:
pkg
of Proto asnull
or change the implement ofgetNamespace
to return "." when pkg == Package.DEFAULT?