1 /*
2  * Copyright (C) 2015 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 #ifndef AAPT_LINKER_H
18 #define AAPT_LINKER_H
19 
20 #include "Resolver.h"
21 #include "ResourceTable.h"
22 #include "ResourceValues.h"
23 #include "Source.h"
24 #include "StringPiece.h"
25 
26 #include <androidfw/AssetManager.h>
27 #include <map>
28 #include <memory>
29 #include <ostream>
30 #include <set>
31 #include <vector>
32 
33 namespace aapt {
34 
35 /**
36  * The Linker has two jobs. It follows resource references
37  * and verifies that their targert exists and that their
38  * types are compatible. The Linker will also assign resource
39  * IDs and fill in all the dependent references with the newly
40  * assigned resource IDs.
41  *
42  * To do this, the Linker builds a graph of references. This
43  * can be useful to do other analysis, like building a
44  * dependency graph of source files. The hope is to be able to
45  * add functionality that operates on the graph without
46  * overcomplicating the Linker.
47  *
48  * TODO(adamlesinski): Build the graph first then run the separate
49  * steps over the graph.
50  */
51 class Linker : ValueVisitor {
52 public:
53     struct Options {
54         /**
55          * Assign resource Ids to references when linking.
56          * When building a static library, set this to false.
57          */
58         bool linkResourceIds = true;
59     };
60 
61     /**
62      * Create a Linker for the given resource table with the sources available in
63      * IResolver. IResolver should contain the ResourceTable as a source too.
64      */
65     Linker(const std::shared_ptr<ResourceTable>& table,
66            const std::shared_ptr<IResolver>& resolver, const Options& options);
67 
68     Linker(const Linker&) = delete;
69 
70     virtual ~Linker() = default;
71 
72     /**
73      * Entry point to the linker. Assigns resource IDs, follows references,
74      * and validates types. Returns true if all references to defined values
75      * are type-compatible. Missing resource references are recorded but do
76      * not cause this method to fail.
77      */
78     bool linkAndValidate();
79 
80     /**
81      * Returns any references to resources that were not defined in any of the
82      * sources.
83      */
84     using ResourceNameToSourceMap = std::map<ResourceName, std::vector<SourceLine>>;
85     const ResourceNameToSourceMap& getUnresolvedReferences() const;
86 
87 protected:
88     virtual void doResolveReference(Reference& reference, const SourceLine& source);
89     virtual const Attribute* doResolveAttribute(Reference& attribute, const SourceLine& source);
90 
91     std::shared_ptr<IResolver> mResolver;
92 
93 private:
94     struct Args : public ValueVisitorArgs {
95         Args(const ResourceNameRef& r, const SourceLine& s);
96 
97         const ResourceNameRef& referrer;
98         const SourceLine& source;
99     };
100 
101     //
102     // Overrides of ValueVisitor
103     //
104     void visit(Reference& reference, ValueVisitorArgs& args) override;
105     void visit(Attribute& attribute, ValueVisitorArgs& args) override;
106     void visit(Styleable& styleable, ValueVisitorArgs& args) override;
107     void visit(Style& style, ValueVisitorArgs& args) override;
108     void visit(Array& array, ValueVisitorArgs& args) override;
109     void visit(Plural& plural, ValueVisitorArgs& args) override;
110 
111     void processAttributeValue(const ResourceNameRef& name, const SourceLine& source,
112                                const Attribute& attr, std::unique_ptr<Item>& value);
113 
114     void addUnresolvedSymbol(const ResourceNameRef& name, const SourceLine& source);
115 
116     std::shared_ptr<ResourceTable> mTable;
117     std::map<ResourceName, std::vector<SourceLine>> mUnresolvedSymbols;
118     Options mOptions;
119     bool mError;
120 };
121 
122 } // namespace aapt
123 
124 #endif // AAPT_LINKER_H
125