Search in sources :

Example 6 with ProgramType

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

the class CServiceTest method setUp.

@Before
public void setUp() throws IOException {
    File numeric = ResourceUtils.copyResourceTo("/parser/calculator/number.thrift", tmp.getRoot());
    File calculator = ResourceUtils.copyResourceTo("/parser/calculator/calculator.thrift", tmp.getRoot());
    ProgramRegistry registry = new ProgramRegistry();
    ThriftProgramParser parser = new ThriftProgramParser();
    ProgramConverter converter = new ProgramConverter(registry);
    ProgramType program = parser.parse(new FileInputStream(numeric), numeric, ImmutableList.of(tmp.getRoot()));
    registry.putProgram(numeric.getCanonicalPath(), converter.convert(numeric.getCanonicalPath(), program));
    program = parser.parse(new FileInputStream(calculator), calculator, ImmutableList.of(tmp.getRoot()));
    registry.putProgram(calculator.getCanonicalPath(), converter.convert(calculator.getCanonicalPath(), program));
    this.registry = registry.registryForPath(calculator.getCanonicalPath());
}
Also used : ProgramRegistry(net.morimekta.providence.reflect.util.ProgramRegistry) ProgramConverter(net.morimekta.providence.reflect.util.ProgramConverter) ProgramType(net.morimekta.providence.model.ProgramType) File(java.io.File) ThriftProgramParser(net.morimekta.providence.reflect.parser.ThriftProgramParser) FileInputStream(java.io.FileInputStream) Before(org.junit.Before)

Example 7 with ProgramType

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

the class ThriftProgramParserTest method testParse_calculator.

@Test
public void testParse_calculator() throws IOException, ParseException {
    copyResourceTo("/parser/calculator/number.thrift", tmp.getRoot());
    copyResourceTo("/parser/calculator/calculator.thrift", tmp.getRoot());
    File calculator = new File(tmp.getRoot(), "calculator.thrift");
    ThriftProgramParser parser = new ThriftProgramParser();
    ProgramType program = parser.parse(new FileInputStream(calculator), calculator, new TreeSet<>());
    assertThat(debugString(program), is(equalToLines("{\n" + "  program_name = \"calculator\"\n" + "  includes = [\n" + "    \"number.thrift\"\n" + "  ]\n" + "  namespaces = {\n" + "    \"java\": \"net.morimekta.test.calculator\"\n" + "  }\n" + "  decl = [\n" + "    {\n" + "      decl_enum = {\n" + "        documentation = \"Block comment on type.\"\n" + "        name = \"Operator\"\n" + "        values = [\n" + "          {\n" + "            documentation = \"line comment on enum\"\n" + "            name = \"IDENTITY\"\n" + "            id = 1\n" + "          },\n" + "          {\n" + "            documentation = \"Block comment on enum.\"\n" + "            name = \"ADD\"\n" + "            id = 2\n" + "          },\n" + "          {\n" + "            name = \"SUBTRACT\"\n" + "            id = 3\n" + "          },\n" + "          {\n" + "            name = \"MULTIPLY\"\n" + "            id = 4\n" + "          },\n" + "          {\n" + "            name = \"DIVIDE\"\n" + "            id = 5\n" + "          }\n" + "        ]\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_struct = {\n" + "        documentation = \"Line comment on type.\"\n" + "        variant = UNION\n" + "        name = \"Operand\"\n" + "        fields = [\n" + "          {\n" + "            documentation = \"Double line\\ncomment on field.\"\n" + "            id = 1\n" + "            type = \"Operation\"\n" + "            name = \"operation\"\n" + "          },\n" + "          {\n" + "            documentation = \"Block comment\\n - with formatting.\\nOn field.\"\n" + "            id = 2\n" + "            type = \"double\"\n" + "            name = \"number\"\n" + "          },\n" + "          {\n" + "            id = 3\n" + "            type = \"number.Imaginary\"\n" + "            name = \"imaginary\"\n" + "          }\n" + "        ]\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_struct = {\n" + "        name = \"Operation\"\n" + "        fields = [\n" + "          {\n" + "            id = 1\n" + "            type = \"Operator\"\n" + "            name = \"operator\"\n" + "          },\n" + "          {\n" + "            id = 2\n" + "            type = \"list<Operand>\"\n" + "            name = \"operands\"\n" + "          }\n" + "        ]\n" + "        annotations = {\n" + "          \"compact\": \"\"\n" + "        }\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_struct = {\n" + "        variant = EXCEPTION\n" + "        name = \"CalculateException\"\n" + "        fields = [\n" + "          {\n" + "            id = 1\n" + "            requirement = REQUIRED\n" + "            type = \"string\"\n" + "            name = \"message\"\n" + "          },\n" + "          {\n" + "            id = 2\n" + "            type = \"Operation\"\n" + "            name = \"operation\"\n" + "          }\n" + "        ]\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_service = {\n" + "        name = \"BaseCalculator\"\n" + "        methods = [\n" + "          {\n" + "            documentation = \"line comment on method.\"\n" + "            one_way = true\n" + "            name = \"iamalive\"\n" + "            params = []\n" + "          },\n" + "          {\n" + "            return_type = \"i32\"\n" + "            name = \"numCalls\"\n" + "            params = [\n" + "              {\n" + "                id = 1\n" + "                requirement = REQUIRED\n" + "                type = \"i32\"\n" + "                name = \"minus\"\n" + "              },\n" + "              {\n" + "                id = 2\n" + "                requirement = OPTIONAL\n" + "                type = \"i32\"\n" + "                name = \"inAdditionTo\"\n" + "              }\n" + "            ]\n" + "          }\n" + "        ]\n" + "        annotations = {\n" + "          \"deprecated\": \"Because reasons\"\n" + "        }\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_service = {\n" + "        documentation = \"Block comment on service\"\n" + "        name = \"Calculator\"\n" + "        extend = \"BaseCalculator\"\n" + "        methods = [\n" + "          {\n" + "            documentation = \"Block comment on method.\"\n" + "            return_type = \"Operand\"\n" + "            name = \"calculate\"\n" + "            params = [\n" + "              {\n" + "                id = 1\n" + "                type = \"Operation\"\n" + "                name = \"op\"\n" + "              }\n" + "            ]\n" + "            exceptions = [\n" + "              {\n" + "                id = 1\n" + "                type = \"CalculateException\"\n" + "                name = \"ce\"\n" + "              }\n" + "            ]\n" + "          }\n" + "        ]\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_const = {\n" + "        documentation = \"Block comment on constant.\"\n" + "        type = \"Operand\"\n" + "        name = \"PI\"\n" + "        value = \"{\\n  \\\"number\\\": 3.141592\\n}\"\n" + "        start_line_no = 63\n" + "        start_line_pos = 20\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_const = {\n" + "        documentation = \"Line comment on constant.\"\n" + "        type = \"set<Operator>\"\n" + "        name = \"kComplexOperands\"\n" + "        value = \"[\\n    Operator.MULTIPLY,\\n    Operator.DIVIDE\\n]\"\n" + "        start_line_no = 68\n" + "        start_line_pos = 40\n" + "      }\n" + "    }\n" + "  ]\n" + "}")));
}
Also used : ProgramType(net.morimekta.providence.model.ProgramType) File(java.io.File) FileInputStream(java.io.FileInputStream) Test(org.junit.Test)

Example 8 with ProgramType

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

the class ThriftProgramParserTest method testParse_number.

@Test
public void testParse_number() throws IOException {
    copyResourceTo("/parser/calculator/number.thrift", tmp.getRoot());
    File number = new File(tmp.getRoot(), "number.thrift");
    ThriftProgramParser parser = new ThriftProgramParser();
    ProgramType program = parser.parse(new FileInputStream(number), number, new TreeSet<>());
    assertThat(debugString(program), is(equalToLines("{\n" + "  program_name = \"number\"\n" + "  namespaces = {\n" + "    \"java\": \"net.morimekta.test.number\"\n" + "  }\n" + "  decl = [\n" + "    {\n" + "      decl_typedef = {\n" + "        type = \"double\"\n" + "        name = \"real\"\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_struct = {\n" + "        name = \"Imaginary\"\n" + "        fields = [\n" + "          {\n" + "            id = 1\n" + "            requirement = REQUIRED\n" + "            type = \"real\"\n" + "            name = \"v\"\n" + "          },\n" + "          {\n" + "            id = 2\n" + "            type = \"double\"\n" + "            name = \"i\"\n" + "            default_value = \"0.0\"\n" + "            start_line_no = 8\n" + "            start_line_pos = 19\n" + "          }\n" + "        ]\n" + "        annotations = {\n" + "          \"compact\": \"true\"\n" + "        }\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_typedef = {\n" + "        type = \"Imaginary\"\n" + "        name = \"I\"\n" + "      }\n" + "    },\n" + "    {\n" + "      decl_const = {\n" + "        type = \"Imaginary\"\n" + "        name = \"kSqrtMinusOne\"\n" + "        value = \"{\\n  \\\"v\\\": 0.0,\\n  \\\"i\\\": -1.0\\n}\"\n" + "        start_line_no = 13\n" + "        start_line_pos = 33\n" + "      }\n" + "    }\n" + "  ]\n" + "}")));
}
Also used : ProgramType(net.morimekta.providence.model.ProgramType) File(java.io.File) FileInputStream(java.io.FileInputStream) Test(org.junit.Test)

Example 9 with ProgramType

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

the class ThriftProgramParserTest method testRegression.

@Test
public void testRegression() throws IOException {
    File regressed = copyResourceTo("/idl/backend-libraries/common_fileserver.thrift", tmp.getRoot());
    ThriftProgramParser parser = new ThriftProgramParser();
    ProgramType program = parser.parse(new FileInputStream(regressed), regressed, new TreeSet<>());
    assertEquals("{\n" + "  program_name = \"common_fileserver\"\n" + "  namespaces = {}\n" + "  decl = [\n" + "    {\n" + "      decl_struct = {\n" + "        name = \"FileServerConfig\"\n" + "        fields = [\n" + "          {\n" + "            documentation = \"Configuration for the /download… URL.\\nSee https://wiki.trd.zedge.net/operations:cdn:cloudflare\"\n" + "            id = 3\n" + "            requirement = OPTIONAL\n" + "            type = \"i32\"\n" + "            name = \"download_url\"\n" + "          }\n" + "        ]\n" + "      }\n" + "    }\n" + "  ]\n" + "}", debugString(program));
}
Also used : ProgramType(net.morimekta.providence.model.ProgramType) File(java.io.File) FileInputStream(java.io.FileInputStream) Test(org.junit.Test)

Example 10 with ProgramType

use of net.morimekta.providence.model.ProgramType 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

ProgramType (net.morimekta.providence.model.ProgramType)16 File (java.io.File)14 FileInputStream (java.io.FileInputStream)11 Test (org.junit.Test)8 ThriftProgramParser (net.morimekta.providence.reflect.parser.ThriftProgramParser)4 Before (org.junit.Before)4 ArrayList (java.util.ArrayList)3 ProgramConverter (net.morimekta.providence.reflect.util.ProgramConverter)3 ProgramRegistry (net.morimekta.providence.reflect.util.ProgramRegistry)3 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 ServiceType (net.morimekta.providence.model.ServiceType)2 CProgram (net.morimekta.providence.reflect.contained.CProgram)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 BufferedInputStream (java.io.BufferedInputStream)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InputStream (java.io.InputStream)1