summaryrefslogtreecommitdiff
path: root/tools/aapt2/link/ReferenceLinker.h
blob: 770f1e500ac0fc7a5de1ab12f584dde173e4f5aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef AAPT_LINKER_REFERENCELINKER_H
#define AAPT_LINKER_REFERENCELINKER_H

#include "android-base/macros.h"

#include "Resource.h"
#include "ResourceValues.h"
#include "link/Linkers.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
#include "xml/XmlDom.h"

namespace aapt {

// A ValueTransformer that returns fully linked versions of resource and macro references.
class ReferenceLinkerTransformer : public CloningValueTransformer {
 public:
  ReferenceLinkerTransformer(const CallSite& callsite, IAaptContext* context, SymbolTable* symbols,
                             StringPool* string_pool, ResourceTable* table,
                             xml::IPackageDeclStack* decl)
      : CloningValueTransformer(string_pool),
        callsite_(callsite),
        context_(context),
        symbols_(symbols),
        table_(table),
        package_decls_(decl) {
  }

  std::unique_ptr<Reference> TransformDerived(const Reference* value) override;
  std::unique_ptr<Item> TransformItem(const Reference* value) override;
  std::unique_ptr<Style> TransformDerived(const Style* value) override;

  bool HasError() {
    return error_;
  }

 private:
  // Transform a RawString value into a more specific, appropriate value, based on the
  // Attribute. If a non RawString value is passed in, this is an identity transform.
  std::unique_ptr<Item> ParseValueWithAttribute(std::unique_ptr<Item> value, const Attribute* attr);

  const CallSite& callsite_;
  IAaptContext* context_;
  SymbolTable* symbols_;
  ResourceTable* table_;
  xml::IPackageDeclStack* package_decls_;
  bool error_ = false;
};

// Resolves all references to resources in the ResourceTable and assigns them IDs.
// The ResourceTable must already have IDs assigned to each resource.
// Once the ResourceTable is processed by this linker, it is ready to be flattened.
class ReferenceLinker : public IResourceTableConsumer {
 public:
  ReferenceLinker() = default;

  // Performs name mangling and looks up the resource in the symbol table. Uses the callsite's
  // package if the reference has no package name defined (implicit).
  // Returns nullptr if the symbol was not found.
  static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference,
                                                  const CallSite& callsite,
                                                  IAaptContext* context,
                                                  SymbolTable* symbols);

  // Performs name mangling and looks up the resource in the symbol table. If the symbol is not
  // visible by the reference at the callsite, nullptr is returned.
  // `out_error` holds the error message.
  static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference,
                                                                 const CallSite& callsite,
                                                                 IAaptContext* context,
                                                                 SymbolTable* symbols,
                                                                 std::string* out_error);

  // Same as ResolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute.
  // That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute.
  static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference,
                                                                    const CallSite& callsite,
                                                                    IAaptContext* context,
                                                                    SymbolTable* symbols,
                                                                    std::string* out_error);

  // Resolves the attribute reference and returns an xml::AaptAttribute if successful.
  // If resolution fails, outError holds the error message.
  static Maybe<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference,
                                                       const CallSite& callsite,
                                                       IAaptContext* context,
                                                       SymbolTable* symbols,
                                                       std::string* out_error);

  // Writes the resource name to the DiagMessage, using the
  // "orig_name (aka <transformed_name>)" syntax.
  /*static void WriteResourceName(const Reference& orig, const CallSite& callsite,
                                const xml::IPackageDeclStack* decls, DiagMessage* out_msg);*/

  // Same as WriteResourceName but omits the 'attr' part.
  static void WriteAttributeName(const Reference& ref, const CallSite& callsite,
                                 const xml::IPackageDeclStack* decls, DiagMessage* out_msg);

  // Returns a fully linked version a resource reference.
  //
  // If the reference points to a non-macro resource, the xml::IPackageDeclStack is used to
  // determine the fully qualified name of the referenced resource. If the symbol is visible
  // to the reference at the callsite, a copy of the reference with an updated updated ID is
  // returned.
  //
  // If the reference points to a macro, the ResourceTable is used to find the macro definition and
  // substitute its contents in place of the reference.
  //
  // Returns nullptr on failure, and an error message is logged to the IDiagnostics in the context.
  static std::unique_ptr<Item> LinkReference(const CallSite& callsite, const Reference& reference,
                                             IAaptContext* context, SymbolTable* symbols,
                                             ResourceTable* table,
                                             const xml::IPackageDeclStack* decls);

  // Links all references in the ResourceTable.
  bool Consume(IAaptContext* context, ResourceTable* table) override;

 private:
  DISALLOW_COPY_AND_ASSIGN(ReferenceLinker);
};

}  // namespace aapt

#endif /* AAPT_LINKER_REFERENCELINKER_H */