Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proto.getNamespace() returns double point string which lead element in no package declared proto can not be resolved #79

Open
timeaftertime opened this issue May 12, 2022 · 1 comment
Assignees

Comments

@timeaftertime
Copy link

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?
@kshchepanovskyi
Copy link
Member

Sorry for late reply.
It's definitely valid to have proto file with unspecified package. I'll check this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants