Search in sources :

Example 1 with ConstType

use of net.morimekta.providence.model.ConstType in project providence by morimekta.

the class ProgramConverter method convert.

/**
 * Convert document model to declared document.
 *
 * @param path The program file path.
 * @param path Path of the program file to convert.
 * @param program Program model to convert.
 * @return The declared thrift document.
 */
public CProgram convert(String path, ProgramType program) {
    ImmutableList.Builder<PDeclaredDescriptor<?>> declaredTypes = ImmutableList.builder();
    ImmutableList.Builder<CConst> constants = ImmutableList.builder();
    ImmutableMap.Builder<String, String> typedefs = ImmutableMap.builder();
    ImmutableList.Builder<CService> services = ImmutableList.builder();
    RecursiveTypeRegistry registry = programRegistry.registryForPath(path);
    File dir = new File(path).getParentFile();
    if (program.hasIncludes()) {
        for (String include : program.getIncludes()) {
            String includePath = new File(dir, include).getPath();
            registry.registerInclude(ReflectionUtils.programNameFromPath(include), programRegistry.registryForPath(includePath));
        }
    }
    for (Declaration decl : program.getDecl()) {
        switch(decl.unionField()) {
            case DECL_ENUM:
                {
                    EnumType enumType = decl.getDeclEnum();
                    int nextValue = PEnumDescriptor.DEFAULT_FIRST_VALUE;
                    CEnumDescriptor type = new CEnumDescriptor(enumType.getDocumentation(), program.getProgramName(), enumType.getName(), enumType.getAnnotations());
                    List<CEnumValue> values = new ArrayList<>();
                    for (EnumValue value : enumType.getValues()) {
                        int v = value.hasId() ? value.getId() : nextValue;
                        nextValue = v + 1;
                        values.add(new CEnumValue(value.getDocumentation(), value.getId(), value.getName(), type, value.getAnnotations()));
                    }
                    type.setValues(values);
                    declaredTypes.add(type);
                    registry.register(type);
                    break;
                }
            case DECL_STRUCT:
                {
                    MessageType messageType = decl.getDeclStruct();
                    List<CField> fields = new ArrayList<>();
                    if (messageType.hasFields()) {
                        fields.addAll(messageType.getFields().stream().map(field -> makeField(registry, program.getProgramName(), field, messageType.getVariant())).collect(Collectors.toList()));
                    }
                    PMessageDescriptor<?, ?> type;
                    switch(messageType.getVariant()) {
                        case STRUCT:
                            type = new CStructDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        case UNION:
                            type = new CUnionDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        case EXCEPTION:
                            type = new CExceptionDescriptor(messageType.getDocumentation(), program.getProgramName(), messageType.getName(), fields, messageType.getAnnotations());
                            break;
                        default:
                            throw new UnsupportedOperationException("Unhandled message variant " + messageType.getVariant());
                    }
                    declaredTypes.add(type);
                    registry.register(type);
                    break;
                }
            case DECL_CONST:
                {
                    ConstType constant = decl.getDeclConst();
                    constants.add(makeConst(registry, program.getProgramName(), constant));
                    break;
                }
            case DECL_TYPEDEF:
                {
                    typedefs.put(decl.getDeclTypedef().getName(), decl.getDeclTypedef().getType());
                    registry.registerTypedef(decl.getDeclTypedef().getName(), program.getProgramName(), decl.getDeclTypedef().getType());
                    break;
                }
            case DECL_SERVICE:
                {
                    ServiceType serviceType = decl.getDeclService();
                    ImmutableList.Builder<CServiceMethod> methodBuilder = ImmutableList.builder();
                    if (serviceType.hasMethods()) {
                        for (FunctionType sm : serviceType.getMethods()) {
                            List<CField> rqFields = new ArrayList<>();
                            if (sm.numParams() > 0) {
                                for (FieldType field : sm.getParams()) {
                                    rqFields.add(makeField(registry, program.getProgramName(), field, MessageVariant.STRUCT));
                                }
                            }
                            CStructDescriptor request = new CStructDescriptor(null, program.getProgramName(), serviceType.getName() + '.' + sm.getName() + ".request", rqFields, null);
                            CUnionDescriptor response = null;
                            if (!sm.isOneWay()) {
                                List<CField> rsFields = new ArrayList<>();
                                CField success;
                                if (sm.getReturnType() != null) {
                                    PDescriptorProvider type = registry.getProvider(sm.getReturnType(), program.getProgramName(), sm.getAnnotations());
                                    success = new CField(null, 0, PRequirement.OPTIONAL, "success", type, null, null);
                                } else {
                                    success = new CField(null, 0, PRequirement.OPTIONAL, "success", PPrimitive.VOID.provider(), null, null);
                                }
                                rsFields.add(success);
                                if (sm.numExceptions() > 0) {
                                    for (FieldType field : sm.getExceptions()) {
                                        rsFields.add(makeField(registry, program.getProgramName(), field, MessageVariant.UNION));
                                    }
                                }
                                response = new CUnionDescriptor(null, program.getProgramName(), serviceType.getName() + '.' + sm.getName() + ".response", rsFields, null);
                            }
                            CServiceMethod method = new CServiceMethod(sm.getDocumentation(), sm.getName(), sm.isOneWay(), request, response, sm.getAnnotations());
                            methodBuilder.add(method);
                        }
                    // for each method
                    }
                    // if has methods
                    PServiceProvider extendsProvider = null;
                    if (serviceType.hasExtend()) {
                        extendsProvider = registry.getServiceProvider(serviceType.getExtend(), program.getProgramName());
                    }
                    CService service = new CService(serviceType.getDocumentation(), program.getProgramName(), serviceType.getName(), extendsProvider, methodBuilder.build(), serviceType.getAnnotations());
                    services.add(service);
                    registry.registerRecursively(service);
                }
        }
    }
    return new CProgram(path, program.getDocumentation(), program.getProgramName(), program.getNamespaces(), getIncludedProgramNames(program), program.getIncludes(), typedefs.build(), declaredTypes.build(), services.build(), constants.build());
}
Also used : PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor) PPrimitive(net.morimekta.providence.descriptor.PPrimitive) PDeclaredDescriptor(net.morimekta.providence.descriptor.PDeclaredDescriptor) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) EnumValue(net.morimekta.providence.model.EnumValue) ReflectionUtils.programNameFromPath(net.morimekta.providence.reflect.util.ReflectionUtils.programNameFromPath) CExceptionDescriptor(net.morimekta.providence.reflect.contained.CExceptionDescriptor) TypeRegistry(net.morimekta.providence.util.TypeRegistry) EnumType(net.morimekta.providence.model.EnumType) CService(net.morimekta.providence.reflect.contained.CService) PServiceProvider(net.morimekta.providence.descriptor.PServiceProvider) CConst(net.morimekta.providence.reflect.contained.CConst) ImmutableMap(com.google.common.collect.ImmutableMap) CProgram(net.morimekta.providence.reflect.contained.CProgram) Declaration(net.morimekta.providence.model.Declaration) Set(java.util.Set) ConstType(net.morimekta.providence.model.ConstType) Collectors(java.util.stream.Collectors) File(java.io.File) PDescriptorProvider(net.morimekta.providence.descriptor.PDescriptorProvider) CUnionDescriptor(net.morimekta.providence.reflect.contained.CUnionDescriptor) MessageVariant(net.morimekta.providence.model.MessageVariant) List(java.util.List) MessageType(net.morimekta.providence.model.MessageType) CEnumDescriptor(net.morimekta.providence.reflect.contained.CEnumDescriptor) CField(net.morimekta.providence.reflect.contained.CField) FunctionType(net.morimekta.providence.model.FunctionType) CStructDescriptor(net.morimekta.providence.reflect.contained.CStructDescriptor) PRequirement(net.morimekta.providence.descriptor.PRequirement) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) ServiceType(net.morimekta.providence.model.ServiceType) FieldType(net.morimekta.providence.model.FieldType) ProgramType(net.morimekta.providence.model.ProgramType) CServiceMethod(net.morimekta.providence.reflect.contained.CServiceMethod) ImmutableList(com.google.common.collect.ImmutableList) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) EnumValue(net.morimekta.providence.model.EnumValue) CServiceMethod(net.morimekta.providence.reflect.contained.CServiceMethod) CUnionDescriptor(net.morimekta.providence.reflect.contained.CUnionDescriptor) EnumType(net.morimekta.providence.model.EnumType) ServiceType(net.morimekta.providence.model.ServiceType) CField(net.morimekta.providence.reflect.contained.CField) CConst(net.morimekta.providence.reflect.contained.CConst) CService(net.morimekta.providence.reflect.contained.CService) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Declaration(net.morimekta.providence.model.Declaration) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) CStructDescriptor(net.morimekta.providence.reflect.contained.CStructDescriptor) ConstType(net.morimekta.providence.model.ConstType) MessageType(net.morimekta.providence.model.MessageType) CEnumValue(net.morimekta.providence.reflect.contained.CEnumValue) FunctionType(net.morimekta.providence.model.FunctionType) ImmutableMap(com.google.common.collect.ImmutableMap) FieldType(net.morimekta.providence.model.FieldType) PServiceProvider(net.morimekta.providence.descriptor.PServiceProvider) CProgram(net.morimekta.providence.reflect.contained.CProgram) PDeclaredDescriptor(net.morimekta.providence.descriptor.PDeclaredDescriptor) CEnumDescriptor(net.morimekta.providence.reflect.contained.CEnumDescriptor) File(java.io.File) PDescriptorProvider(net.morimekta.providence.descriptor.PDescriptorProvider) CExceptionDescriptor(net.morimekta.providence.reflect.contained.CExceptionDescriptor)

Example 2 with ConstType

use of net.morimekta.providence.model.ConstType in project providence by morimekta.

the class ThriftProgramParser method parseInternal.

private ProgramType parseInternal(InputStream in, File file, Collection<File> includeDirs) throws IOException {
    ProgramType._Builder program = ProgramType.builder();
    String programName = ReflectionUtils.programNameFromPath(file.getName());
    if (!VALID_PROGRAM_NAME.matcher(programName).matches()) {
        throw new ParseException("Program name \"%s\" derived from filename \"%s\" is not valid.", Strings.escape(programName), Strings.escape(file.getName()));
    }
    program.setProgramName(programName);
    List<String> include_files = new ArrayList<>();
    Set<String> includedPrograms = new HashSet<>();
    Map<String, String> namespaces = new LinkedHashMap<>();
    List<Declaration> declarations = new ArrayList<>();
    ThriftTokenizer tokenizer = new ThriftTokenizer(in);
    boolean has_header = false;
    boolean hasDeclaration = false;
    String doc_string = null;
    Token token;
    while ((token = tokenizer.next()) != null) {
        if (token.strEquals(kLineCommentStart)) {
            doc_string = parseDocLine(tokenizer, doc_string);
            continue;
        } else if (token.strEquals(kBlockCommentStart)) {
            doc_string = tokenizer.parseDocBlock();
            continue;
        }
        String keyword = token.asString();
        if (!Model_Constants.kThriftKeywords.contains(keyword)) {
            throw tokenizer.failure(token, "Unexpected token \'%s\'", token.asString());
        }
        switch(keyword) {
            case kNamespace:
                if (hasDeclaration) {
                    throw tokenizer.failure(token, "Unexpected token 'namespace', expected type declaration");
                }
                if (doc_string != null && !has_header) {
                    program.setDocumentation(doc_string);
                }
                doc_string = null;
                has_header = true;
                parseNamespace(tokenizer, namespaces);
                break;
            case kInclude:
                if (hasDeclaration) {
                    throw tokenizer.failure(token, "Unexpected token 'include', expected type declaration");
                }
                if (doc_string != null && !has_header) {
                    program.setDocumentation(doc_string);
                }
                doc_string = null;
                has_header = true;
                parseIncludes(tokenizer, include_files, file, includedPrograms, includeDirs);
                break;
            case kTypedef:
                has_header = true;
                hasDeclaration = true;
                parseTypedef(tokenizer, doc_string, declarations, includedPrograms);
                doc_string = null;
                break;
            case kEnum:
                has_header = true;
                hasDeclaration = true;
                EnumType et = parseEnum(tokenizer, doc_string);
                declarations.add(Declaration.withDeclEnum(et));
                doc_string = null;
                break;
            case kStruct:
            case kUnion:
            case kException:
                has_header = true;
                hasDeclaration = true;
                MessageType st = parseMessage(tokenizer, token.asString(), doc_string, includedPrograms);
                declarations.add(Declaration.withDeclStruct(st));
                doc_string = null;
                break;
            case kService:
                has_header = true;
                hasDeclaration = true;
                ServiceType srv = parseService(tokenizer, doc_string, includedPrograms);
                declarations.add(Declaration.withDeclService(srv));
                doc_string = null;
                break;
            case kConst:
                has_header = true;
                hasDeclaration = true;
                ConstType cnst = parseConst(tokenizer, doc_string, includedPrograms);
                declarations.add(Declaration.withDeclConst(cnst));
                doc_string = null;
                break;
            default:
                throw tokenizer.failure(token, "Unexpected token \'%s\'", Strings.escape(token.asString()));
        }
    }
    if (namespaces.size() > 0) {
        program.setNamespaces(namespaces);
    }
    if (include_files.size() > 0) {
        program.setIncludes(include_files);
    }
    if (declarations.size() > 0) {
        program.setDecl(declarations);
    }
    return program.build();
}
Also used : ThriftTokenizer(net.morimekta.providence.reflect.parser.internal.ThriftTokenizer) ArrayList(java.util.ArrayList) Token(net.morimekta.providence.serializer.pretty.Token) LinkedHashMap(java.util.LinkedHashMap) EnumType(net.morimekta.providence.model.EnumType) ServiceType(net.morimekta.providence.model.ServiceType) ProgramType(net.morimekta.providence.model.ProgramType) Declaration(net.morimekta.providence.model.Declaration) ConstType(net.morimekta.providence.model.ConstType) MessageType(net.morimekta.providence.model.MessageType) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)2 ConstType (net.morimekta.providence.model.ConstType)2 Declaration (net.morimekta.providence.model.Declaration)2 EnumType (net.morimekta.providence.model.EnumType)2 MessageType (net.morimekta.providence.model.MessageType)2 ProgramType (net.morimekta.providence.model.ProgramType)2 ServiceType (net.morimekta.providence.model.ServiceType)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 File (java.io.File)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1 Collectors (java.util.stream.Collectors)1 PDeclaredDescriptor (net.morimekta.providence.descriptor.PDeclaredDescriptor)1 PDescriptorProvider (net.morimekta.providence.descriptor.PDescriptorProvider)1 PEnumDescriptor (net.morimekta.providence.descriptor.PEnumDescriptor)1 PMessageDescriptor (net.morimekta.providence.descriptor.PMessageDescriptor)1