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