zeek/src/zeekygen/IdentifierInfo.h

204 lines
5.9 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <time.h> // for time_t
#include <list>
#include <map>
#include <string>
#include <vector>
#include "zeek/ID.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/util.h"
#include "zeek/zeekygen/Info.h"
namespace zeek
{
class TypeDecl;
namespace zeekygen::detail
{
class ScriptInfo;
/**
* Information regarding a script-level identifier and its documentation.
*/
class IdentifierInfo : public Info
{
public:
/**
* Create a new identifier info object.
* @param id The script-level identifier.
* @param script The info object associated with the script in which \a id
* is declared.
* @param from_redef Whether the identifier was create as part of a
* redefinition (e.g. an enum).
*/
IdentifierInfo(zeek::detail::IDPtr id, ScriptInfo* script, bool from_redef = false);
/**
* Dtor. Releases any references to script-level objects.
*/
~IdentifierInfo() override;
/**
* Returns the initial value of the identifier.
*/
const ValPtr& InitialVal() const { return initial_val; }
/**
* Add a comment associated with the identifier. If the identifier is a
* record type and it's in the middle of parsing fields, the comment is
* associated with the last field that was parsed.
* @param comment A string extracted from Zeekygen-style comment.
*/
void AddComment(const std::string& comment)
{
last_field_seen ? last_field_seen->comments.push_back(comment)
: comments.push_back(comment);
}
/**
* Associate several comments with the identifier. They will be appended
* to the end of the list of any current comments.
* @param cmtns A vector of comments to associate.
*/
void AddComments(const std::vector<std::string>& cmtns)
{
comments.insert(comments.end(), cmtns.begin(), cmtns.end());
}
/**
* Register a redefinition of the identifier.
* @param from_script The script in which the redef occurred.
* @param ic The initialization class used (e.g. =, +=, -=)
* @param init_expr The initialization expression used.
* @param comments Comments associated with the redef statement.
*/
void AddRedef(const std::string& from_script, zeek::detail::InitClass ic,
zeek::detail::ExprPtr init_expr, const std::vector<std::string>& comments);
/**
* Register a record field associated with the identifier
* (which is implicitly a record type).
* @param field The name/type information of the field.
* @param script The script in which the field was declared. This may
* differ from the script in which a record type is declared due to redefs.
* @param comments Comments associated with the record field.
* @param from_redef The field is from a record redefinition.
*/
void AddRecordField(const TypeDecl* field, const std::string& script,
std::vector<std::string>& comments, bool from_redef);
/**
* Signals that a record type has been completely parsed. This resets
* internal tracking of the last record field seen so that "##<"-style
* comments are correctly associated.
*/
void CompletedTypeDecl() { last_field_seen = nullptr; }
/**
* @return the script-level ID tracked by this info object.
*/
zeek::detail::ID* GetID() const { return id.get(); }
/**
* @return The script which declared the script-level identifier.
*/
ScriptInfo* GetDeclaringScript() const { return declaring_script; }
/**
* @param field A record field name.
* @return The script which declared the record field name.
*/
std::string GetDeclaringScriptForField(const std::string& field) const;
/**
* @return True if the identifier was created as part of a redefinition
* (e.g. an enum).
*/
bool IsFromRedef() const { return from_redef; }
/**
* @param field A record field name.
* @return True if the field name was added to a record as part of a redef.
*/
bool FieldIsFromRedef(const std::string& field) const;
/**
* @return All Zeekygen comments associated with the identifier.
*/
std::vector<std::string> GetComments() const;
/**
* @param field A record field name.
* @return All Zeekygen comments associated with the record field.
*/
std::vector<std::string> GetFieldComments(const std::string& field) const;
/**
* Tracks useful information related to a redef.
*/
struct Redefinition
{
std::string from_script; /**< Name of script doing the redef. */
zeek::detail::InitClass ic;
zeek::detail::ExprPtr init_expr;
std::vector<std::string> comments; /**< Zeekygen comments on redef. */
Redefinition(std::string arg_script, zeek::detail::InitClass arg_ic,
zeek::detail::ExprPtr arg_expr, std::vector<std::string> arg_comments);
~Redefinition();
};
/**
* Get a list of information about redefinitions of the identifier within
* a particular script.
* @param from_script The name of a script in which to look for redefs.
* @return A list of redefs that occurred in \a from_script.
*/
std::list<Redefinition> GetRedefs(const std::string& from_script) const;
/**
* Get a list of information about redefinitions of the identifier.
* @return A list of redefs that occurred for the identifier.
*/
const std::list<Redefinition*>& GetRedefs() const { return redefs; }
private:
time_t DoGetModificationTime() const override;
std::string DoName() const override { return id->Name(); }
std::string DoReStructuredText(bool roles_only) const override;
struct RecordField
{
~RecordField();
TypeDecl* field;
std::string from_script;
std::vector<std::string> comments;
bool from_redef;
};
using redef_list = std::list<Redefinition*>;
using record_field_map = std::map<std::string, RecordField*>;
std::vector<std::string> comments;
zeek::detail::IDPtr id;
ValPtr initial_val;
redef_list redefs;
record_field_map fields;
RecordField* last_field_seen;
ScriptInfo* declaring_script;
bool from_redef = false;
};
} // namespace zeekygen::detail
} // namespace zeek