1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
6#define ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
7
8#include <fidl/flat_ast.h>
9#include <fidl/json_generator.h>
10#include <fidl/lexer.h>
11#include <fidl/parser.h>
12#include <fidl/source_file.h>
13
14static fidl::SourceFile MakeSourceFile(const std::string& filename, const std::string& raw_source_code) {
15    std::string source_code(raw_source_code);
16    // NUL terminate the string.
17    source_code.resize(source_code.size() + 1);
18    return fidl::SourceFile(filename, source_code);
19}
20
21class TestLibrary {
22public:
23    TestLibrary(const std::string& filename, const std::string& raw_source_code)
24        : source_file_(MakeSourceFile(filename, raw_source_code)),
25          lexer_(source_file_, &identifier_table_),
26          parser_(&lexer_, &error_reporter_),
27          library_(std::make_unique<fidl::flat::Library>(&all_libraries_, &error_reporter_)) {
28    }
29
30    bool AddDependentLibrary(TestLibrary& dependent_library) {
31        // For testing, we have conveniences to construct compiled test
32        // libraries, which we usurp here to move it into the current library
33        // under test. This would be made clearer with a helper object which
34        // owned all libraries under test.
35        if (!all_libraries_.Insert(std::unique_ptr<fidl::flat::Library>(dependent_library.library_.get()))) {
36            return false;
37        }
38        dependent_library.library_.release();
39        return true;
40    }
41
42    bool Parse(std::unique_ptr<fidl::raw::File>& ast_ptr) {
43        ast_ptr.reset(parser_.Parse().release());
44        return parser_.Ok();
45    }
46
47    bool Compile() {
48        auto ast = parser_.Parse();
49        return parser_.Ok() &&
50               library_->ConsumeFile(std::move(ast)) &&
51               library_->Compile();
52    }
53
54    std::string GenerateJSON() {
55        auto json_generator = fidl::JSONGenerator(library_.get());
56        auto out = json_generator.Produce();
57        return out.str();
58    }
59
60    bool AddSourceFile(const std::string& filename, const std::string& raw_source_code) {
61        auto source_file = MakeSourceFile(filename, raw_source_code);
62        fidl::IdentifierTable identifier_table;
63        fidl::Lexer lexer(source_file, &identifier_table);
64        fidl::Parser parser(&lexer, &error_reporter_);
65        auto ast = parser.Parse();
66        return parser.Ok() &&
67               library_->ConsumeFile(std::move(ast)) &&
68               library_->Compile();
69    }
70
71    const fidl::flat::Struct* LookupStruct(const std::string& name) {
72        for (const auto& struct_decl : library_->struct_declarations_) {
73            if (struct_decl->GetName() == name) {
74                return struct_decl.get();
75            }
76        }
77        return nullptr;
78    }
79
80    const fidl::flat::Table* LookupTable(const std::string& name) {
81        for (const auto& table_decl : library_->table_declarations_) {
82            if (table_decl->GetName() == name) {
83                return table_decl.get();
84            }
85        }
86        return nullptr;
87    }
88
89    const fidl::flat::Union* LookupUnion(const std::string& name) {
90        for (const auto& union_decl : library_->union_declarations_) {
91            if (union_decl->GetName() == name) {
92                return union_decl.get();
93            }
94        }
95        return nullptr;
96    }
97
98    const fidl::flat::Interface* LookupInterface(const std::string& name) {
99        for (const auto& interface_decl : library_->interface_declarations_) {
100            if (interface_decl->GetName() == name) {
101                return interface_decl.get();
102            }
103        }
104        return nullptr;
105    }
106
107    fidl::SourceFile source_file() {
108        return source_file_;
109    }
110
111    const std::vector<std::string>& errors() const {
112        return error_reporter_.errors();
113    }
114
115private:
116    fidl::SourceFile source_file_;
117    fidl::IdentifierTable identifier_table_;
118    fidl::ErrorReporter error_reporter_;
119    fidl::Lexer lexer_;
120    fidl::Parser parser_;
121    fidl::flat::Libraries all_libraries_;
122    std::unique_ptr<fidl::flat::Library> library_;
123};
124
125#endif // ZIRCON_SYSTEM_UTEST_FIDL_COMPILER_TEST_LIBRARY_H_
126