refactor: type resolution using visitor
Type references and constant references are done in a same visitor.
Visitor provides "scope" which can be used to (not implemented in this
change)
- resolve "type parameter"(AidlTypeSpecifier) bound to the scope
- resolve nested types
- ...
Bug: n/a
Test: aidl_unittests
Change-Id: I44aef519545ca377b208dbe98ef5a57b9cec1878
diff --git a/aidl_language.h b/aidl_language.h
index e0c28a0..fcc592a 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -700,8 +700,10 @@
const std::string& GetFieldName() const { return field_name_; }
bool CheckValid() const override;
- void TraverseChildren(std::function<void(const AidlNode&)>) const override {
- // resolved_ is not my child.
+ void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
+ if (ref_type_) {
+ traverse(*ref_type_);
+ }
}
void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
const AidlConstantValue* Resolve(const AidlDefinedType* scope) const;
@@ -1249,4 +1251,17 @@
n.TraverseChildren(top_down);
};
top_down(node);
+}
+
+// Utility to make a visitor to visit AST tree in bottom-up order
+// Given: foo
+// / \
+// bar baz
+// VisitBottomUp(v, foo) makes v visit bar -> baz -> foo.
+inline void VisitBottomUp(AidlVisitor& v, const AidlNode& node) {
+ std::function<void(const AidlNode&)> bottom_up = [&](const AidlNode& n) {
+ n.TraverseChildren(bottom_up);
+ n.DispatchVisit(v);
+ };
+ bottom_up(node);
}
\ No newline at end of file
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index ab3e479..19b1262 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -660,7 +660,6 @@
non_array_type
: annotation_list qualified_name {
$$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), false, nullptr, $2->GetComments());
- ps->DeferResolution($$);
if (!$1->empty()) {
$$->SetComments($1->begin()->GetComments());
$$->Annotate(std::move(*$1));
diff --git a/parser.cpp b/parser.cpp
index 721979f..c8cf476 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -61,24 +61,26 @@
}
}
-class ConstantReferenceResolver : public AidlVisitor {
+class ReferenceResolver : public AidlVisitor {
public:
- ConstantReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
- TypeResolver& resolver, bool* success)
+ ReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
+ TypeResolver& resolver, bool* success)
: scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {}
+
+ void Visit(const AidlTypeSpecifier& t) override {
+ AidlTypeSpecifier& type = const_cast<AidlTypeSpecifier&>(t);
+ if (!resolver_(typenames_.GetDocumentFor(scope_), &type)) {
+ AIDL_ERROR(type) << "Failed to resolve '" << type.GetUnresolvedName() << "'";
+ *success_ = false;
+ }
+ }
+
void Visit(const AidlConstantReference& v) override {
if (IsCircularReference(&v)) {
*success_ = false;
return;
}
- if (v.GetRefType() && !v.GetRefType()->IsResolved()) {
- if (!resolver_(typenames_.GetDocumentFor(scope_), v.GetRefType().get())) {
- AIDL_ERROR(v.GetRefType()) << "Unknown type '" << v.GetRefType()->GetName() << "'";
- *success_ = false;
- return;
- }
- }
const AidlConstantValue* resolved = v.Resolve(scope_);
if (!resolved) {
AIDL_ERROR(v) << "Unknown reference '" << v.Literal() << "'";
@@ -88,7 +90,7 @@
// resolve recursive references
Push(&v);
- VisitTopDown(*this, *resolved);
+ VisitBottomUp(*this, *resolved);
Pop();
}
@@ -133,20 +135,13 @@
std::vector<StackElem> stack_ = {};
};
+// Resolve "unresolved" types in the "main" document.
bool Parser::Resolve(TypeResolver& type_resolver) {
bool success = true;
- for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
- if (!type_resolver(document_, typespec)) {
- AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
- success = false;
- // don't stop to show more errors if any
- }
- }
- // resolve "field references" as well.
for (const auto& type : document_->DefinedTypes()) {
- ConstantReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
- VisitTopDown(ref_resolver, *type);
+ ReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
+ VisitBottomUp(ref_resolver, *type);
}
return success;
diff --git a/parser.h b/parser.h
index e2dea08..f34ca78 100644
--- a/parser.h
+++ b/parser.h
@@ -87,12 +87,6 @@
void SetPackage(const std::string& package) { package_ = package; }
const std::string& Package() const { return package_; }
- void DeferResolution(AidlTypeSpecifier* typespec) {
- unresolved_typespecs_.emplace_back(typespec);
- }
-
- const vector<AidlTypeSpecifier*>& GetUnresolvedTypespecs() const { return unresolved_typespecs_; }
-
bool Resolve(TypeResolver& type_resolver);
void SetDocument(std::unique_ptr<AidlDocument>&& document) {
// The parsed document is owned by typenames_. This parser object only has
@@ -121,6 +115,5 @@
YY_BUFFER_STATE buffer_;
int error_ = 0;
- vector<AidlTypeSpecifier*> unresolved_typespecs_;
const AidlDocument* document_;
};