blob: 9351dc34ea547aa406e2b8aa01a91c8d37ab2261 [file] [log] [blame]
Eric Holkc4239ac2018-09-05 10:43:31 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "gflags/gflags.h"
18
Eric Holkdbc36e22018-09-20 12:03:10 -070019#include "dex_builder.h"
Eric Holkc4239ac2018-09-05 10:43:31 -070020#include "java_lang_builder.h"
Eric Holk3cbf1762018-12-13 16:04:56 -080021#include "tinyxml_layout_parser.h"
Eric Holkc4239ac2018-09-05 10:43:31 -070022#include "util.h"
23
24#include "tinyxml2.h"
25
26#include <fstream>
27#include <iostream>
28#include <sstream>
29#include <string>
30#include <vector>
31
Eric Holkdbc36e22018-09-20 12:03:10 -070032namespace {
33
Eric Holkc4239ac2018-09-05 10:43:31 -070034using namespace tinyxml2;
35using std::string;
36
37constexpr char kStdoutFilename[]{"stdout"};
38
Eric Holkdbc36e22018-09-20 12:03:10 -070039DEFINE_bool(dex, false, "Generate a DEX file instead of Java");
Eric Holkc4239ac2018-09-05 10:43:31 -070040DEFINE_string(out, kStdoutFilename, "Where to write the generated class");
Eric Holkdbc36e22018-09-20 12:03:10 -070041DEFINE_string(package, "", "The package name for the generated class (required)");
Eric Holkc4239ac2018-09-05 10:43:31 -070042
Eric Holkc4239ac2018-09-05 10:43:31 -070043class ViewCompilerXmlVisitor : public XMLVisitor {
44 public:
45 ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
46
47 bool VisitEnter(const XMLDocument& /*doc*/) override {
48 builder_->Start();
49 return true;
50 }
51
52 bool VisitExit(const XMLDocument& /*doc*/) override {
53 builder_->Finish();
54 return true;
55 }
56
57 bool VisitEnter(const XMLElement& element, const XMLAttribute* /*firstAttribute*/) override {
58 builder_->StartView(element.Name());
59 return true;
60 }
61
62 bool VisitExit(const XMLElement& /*element*/) override {
63 builder_->FinishView();
64 return true;
65 }
66
67 private:
68 JavaLangViewBuilder* builder_;
69};
Eric Holkdbc36e22018-09-20 12:03:10 -070070
Eric Holkc4239ac2018-09-05 10:43:31 -070071} // end namespace
72
73int main(int argc, char** argv) {
74 constexpr size_t kProgramName = 0;
75 constexpr size_t kFileNameParam = 1;
76 constexpr size_t kNumRequiredArgs = 2;
77
78 gflags::SetUsageMessage(
79 "Compile XML layout files into equivalent Java language code\n"
80 "\n"
81 " example usage: viewcompiler layout.xml --package com.example.androidapp");
82 gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags*/ true);
83
84 gflags::CommandLineFlagInfo cmd = gflags::GetCommandLineFlagInfoOrDie("package");
85 if (argc != kNumRequiredArgs || cmd.is_default) {
86 gflags::ShowUsageWithFlags(argv[kProgramName]);
87 return 1;
88 }
89
Eric Holkdbc36e22018-09-20 12:03:10 -070090 if (FLAGS_dex) {
91 startop::dex::WriteTestDexFile("test.dex");
92 return 0;
93 }
94
Eric Holkc4239ac2018-09-05 10:43:31 -070095 const char* const filename = argv[kFileNameParam];
96 const string layout_name = FindLayoutNameFromFilename(filename);
97
98 // We want to generate Java language code to inflate exactly this layout. This means
99 // generating code to walk the resource XML too.
100
101 XMLDocument xml;
102 xml.LoadFile(filename);
103
Eric Holk3cbf1762018-12-13 16:04:56 -0800104 string message{};
105 if (!startop::CanCompileLayout(xml, &message)) {
106 LOG(ERROR) << "Layout not supported: " << message;
107 return 1;
108 }
109
Eric Holkc4239ac2018-09-05 10:43:31 -0700110 std::ofstream outfile;
111 if (FLAGS_out != kStdoutFilename) {
112 outfile.open(FLAGS_out);
113 }
114 JavaLangViewBuilder builder{
115 FLAGS_package, layout_name, FLAGS_out == kStdoutFilename ? std::cout : outfile};
116
117 ViewCompilerXmlVisitor visitor{&builder};
118 xml.Accept(&visitor);
119
120 return 0;
Eric Holkdbc36e22018-09-20 12:03:10 -0700121}