blob: ff3dace4259ec5d2e8073ececc98959ff7a39451 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_FIDL_FIDLC_SRC_LINTING_TREE_CALLBACKS_H_
#define TOOLS_FIDL_FIDLC_SRC_LINTING_TREE_CALLBACKS_H_
#include <lib/fit/function.h>
#include <vector>
#include "lib/stdcompat/span.h"
#include "tools/fidl/fidlc/src/source_span.h"
#include "tools/fidl/fidlc/src/tree_visitor.h"
namespace fidlc {
// Supports TreeVisitor actions via delegation instead of inheritance, by
// wrapping a TreeVisitor subclass that calls a list of callbacks for
// each visitor method. In other words, this class implements a hardcoded "map"
// from each source node type (represented by its TreeVisitor method) to a set
// of callbacks, rather than implementing the callback logic directly inside
// the overridden method.
class LintingTreeCallbacks {
public:
// Construct a new callbacks container. Call "On" methods, for each event
// type (such as "OnAttribute"), to register a callback for that event.
LintingTreeCallbacks();
// Process a file (initiates the callbacks as each element is visited for
// the given parsed source file).
void Visit(const std::unique_ptr<File>& element);
// Register a callback for a "File" event. All of the remaining "On"
// functions similarly match their corresponding TreeVisitor methods.
void OnFile(fit::function<void(const File&)> callback) {
file_callbacks_.push_back(std::move(callback));
}
void OnExitFile(fit::function<void(const File&)> callback) {
exit_file_callbacks_.push_back(std::move(callback));
}
void OnSourceElement(fit::function<void(const SourceElement&)> callback) {
source_element_callbacks_.push_back(std::move(callback));
}
// If comments lines are broken by more than one newline, they are treated as separate comments.
void OnComment(fit::function<void(const cpp20::span<const SourceSpan>)> callback) {
comment_callbacks_.push_back(std::move(callback));
}
void OnIgnoredToken(fit::function<void(const Token&)> callback) {
ignored_token_callbacks_.push_back(std::move(callback));
}
void OnAliasDeclaration(fit::function<void(const RawAliasDeclaration&)> callback) {
alias_callbacks_.push_back(std::move(callback));
}
void OnUsing(fit::function<void(const RawUsing&)> callback) {
using_callbacks_.push_back(std::move(callback));
}
void OnConstDeclaration(fit::function<void(const RawConstDeclaration&)> callback) {
const_declaration_callbacks_.push_back(std::move(callback));
}
void OnExitConstDeclaration(fit::function<void(const RawConstDeclaration&)> callback) {
exit_const_declaration_callbacks_.push_back(std::move(callback));
}
void OnProtocolDeclaration(fit::function<void(const RawProtocolDeclaration&)> callback) {
protocol_declaration_callbacks_.push_back(std::move(callback));
}
void OnExitProtocolDeclaration(fit::function<void(const RawProtocolDeclaration&)> callback) {
exit_protocol_declaration_callbacks_.push_back(std::move(callback));
}
void OnMethod(fit::function<void(const RawProtocolMethod&)> callback) {
method_callbacks_.push_back(std::move(callback));
}
void OnEvent(fit::function<void(const RawProtocolMethod&)> callback) {
event_callbacks_.push_back(std::move(callback));
}
void OnAttribute(fit::function<void(const RawAttribute&)> callback) {
attribute_callbacks_.push_back(std::move(callback));
}
void OnOrdinaledLayoutMember(fit::function<void(const RawOrdinaledLayoutMember&)> callback) {
ordinaled_layout_member_callbacks_.push_back(std::move(callback));
}
void OnStructLayoutMember(fit::function<void(const RawStructLayoutMember&)> callback) {
struct_layout_member_callbacks_.push_back(std::move(callback));
}
void OnValueLayoutMember(fit::function<void(const RawValueLayoutMember&)> callback) {
value_layout_member_callbacks_.push_back(std::move(callback));
}
void OnLayout(fit::function<void(const RawLayout&)> callback) {
layout_callbacks_.push_back(std::move(callback));
}
void OnExitLayout(fit::function<void(const RawLayout&)> callback) {
exit_layout_callbacks_.push_back(std::move(callback));
}
void OnTypeDeclaration(fit::function<void(const RawTypeDeclaration&)> callback) {
type_decl_callbacks_.push_back(std::move(callback));
}
void OnExitTypeDeclaration(fit::function<void(const RawTypeDeclaration&)> callback) {
exit_type_decl_callbacks_.push_back(std::move(callback));
}
void OnIdentifierLayoutParameter(
fit::function<void(const RawIdentifierLayoutParameter&)> callback) {
identifier_layout_parameter_callbacks_.push_back(std::move(callback));
}
void OnTypeConstructor(fit::function<void(const RawTypeConstructor&)> callback) {
type_constructor_callbacks_.push_back(std::move(callback));
}
private:
// tree_visitor_ is initialized to a locally-defined class
// |CallbackTreeVisitor| defined in the out-of-line implementation of the
// LintingTreeCallbacks constructor.
//
// The CallbackTreeVisitor overrides TreeVisitor to call the registered
// callback methods. It is not necessary to define the class inline here.
// We avoid having to declare all of the overridden methods unnecessarily
// in this header; and avoid the alternative--defining the methods inline,
// in this header--which would make including the header a costly thing to
// do.
std::unique_ptr<TreeVisitor> tree_visitor_;
std::vector<fit::function<void(const File&)>> file_callbacks_;
std::vector<fit::function<void(const File&)>> exit_file_callbacks_;
std::vector<fit::function<void(const SourceElement&)>> source_element_callbacks_;
std::vector<fit::function<void(const cpp20::span<const SourceSpan>)>> comment_callbacks_;
std::vector<fit::function<void(const Token&)>> ignored_token_callbacks_;
std::vector<fit::function<void(const RawAliasDeclaration&)>> alias_callbacks_;
std::vector<fit::function<void(const RawUsing&)>> using_callbacks_;
std::vector<fit::function<void(const RawConstDeclaration&)>> const_declaration_callbacks_;
std::vector<fit::function<void(const RawConstDeclaration&)>> exit_const_declaration_callbacks_;
std::vector<fit::function<void(const RawProtocolDeclaration&)>> protocol_declaration_callbacks_;
std::vector<fit::function<void(const RawProtocolDeclaration&)>>
exit_protocol_declaration_callbacks_;
std::vector<fit::function<void(const RawProtocolMethod&)>> method_callbacks_;
std::vector<fit::function<void(const RawProtocolMethod&)>> event_callbacks_;
std::vector<fit::function<void(const RawAttribute&)>> attribute_callbacks_;
std::vector<fit::function<void(const RawOrdinaledLayoutMember&)>>
ordinaled_layout_member_callbacks_;
std::vector<fit::function<void(const RawStructLayoutMember&)>> struct_layout_member_callbacks_;
std::vector<fit::function<void(const RawValueLayoutMember&)>> value_layout_member_callbacks_;
std::vector<fit::function<void(const RawLayout&)>> layout_callbacks_;
std::vector<fit::function<void(const RawLayout&)>> exit_layout_callbacks_;
std::vector<fit::function<void(const RawIdentifierLayoutParameter&)>>
identifier_layout_parameter_callbacks_;
std::vector<fit::function<void(const RawTypeDeclaration&)>> type_decl_callbacks_;
std::vector<fit::function<void(const RawTypeDeclaration&)>> exit_type_decl_callbacks_;
std::vector<fit::function<void(const RawTypeConstructor&)>> type_constructor_callbacks_;
};
} // namespace fidlc
#endif // TOOLS_FIDL_FIDLC_SRC_LINTING_TREE_CALLBACKS_H_