mirror of https://github.com/Icinga/icinga2.git
parent
76ed38fbfe
commit
c5a170a972
|
@ -244,6 +244,7 @@ const std::vector<String>& ConfigWriter::GetKeywords(void)
|
|||
keywords.push_back("globals");
|
||||
keywords.push_back("locals");
|
||||
keywords.push_back("use");
|
||||
keywords.push_back("__using");
|
||||
keywords.push_back("ignore_on_error");
|
||||
keywords.push_back("current_filename");
|
||||
keywords.push_back("current_line");
|
||||
|
|
|
@ -66,22 +66,22 @@ private:
|
|||
Callback m_Callback;
|
||||
};
|
||||
|
||||
#define REGISTER_SCRIPTFUNCTION(name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#name, WrapFunction(callback)); \
|
||||
ScriptGlobal::Set(#name, sf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SCRIPTFUNCTION_NS(ns, name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), false); \
|
||||
ScriptGlobal::Set(#ns "." #name, sf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SCRIPTFUNCTION_NS_PREFIX(ns, name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), false); \
|
||||
ScriptGlobal::Set(#ns "." #name, sf); \
|
||||
Function::Ptr dsf = new icinga::Function("__" #name " (deprecated)", WrapFunction(callback), false, true); \
|
||||
ScriptGlobal::Set("__" #name, dsf); \
|
||||
ScriptGlobal::Set("System.__" #name, dsf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
@ -97,22 +97,22 @@ private:
|
|||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SAFE_SCRIPTFUNCTION(name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#name, WrapFunction(callback), true); \
|
||||
ScriptGlobal::Set(#name, sf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SAFE_SCRIPTFUNCTION_NS(ns, name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), true); \
|
||||
ScriptGlobal::Set(#ns "." #name, sf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SAFE_SCRIPTFUNCTION_NS_PREFIX(ns, name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## ns ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, WrapFunction(callback), true); \
|
||||
ScriptGlobal::Set(#ns "." #name, sf); \
|
||||
Function::Ptr dsf = new icinga::Function("__" #name " (deprecated)", WrapFunction(callback), true, true); \
|
||||
ScriptGlobal::Set("__" #name, dsf); \
|
||||
ScriptGlobal::Set("System.__" #name, dsf); \
|
||||
} \
|
||||
INITIALIZE_ONCE_WITH_PRIORITY(RegisterFunction, 10); \
|
||||
} } }
|
||||
|
|
|
@ -30,8 +30,15 @@ ScriptFrame::ScriptFrame(void)
|
|||
{
|
||||
std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
|
||||
|
||||
if (frames && !frames->empty())
|
||||
Sandboxed = frames->top()->Sandboxed;
|
||||
if (frames && !frames->empty()) {
|
||||
ScriptFrame *frame = frames->top();
|
||||
|
||||
Sandboxed = frame->Sandboxed;
|
||||
Imports = frame->Imports;
|
||||
} else {
|
||||
Imports = new Array();
|
||||
Imports->Add(ScriptGlobal::Get("System"));
|
||||
}
|
||||
|
||||
PushFrame(this);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config/i2-config.hpp"
|
||||
#include "base/dictionary.hpp"
|
||||
#include "base/array.hpp"
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <stack>
|
||||
|
||||
|
@ -31,6 +32,7 @@ namespace icinga
|
|||
struct I2_BASE_API ScriptFrame
|
||||
{
|
||||
Dictionary::Ptr Locals;
|
||||
Array::Ptr Imports;
|
||||
Value Self;
|
||||
bool Sandboxed;
|
||||
int Depth;
|
||||
|
|
|
@ -37,35 +37,35 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(match, &Utility::Match);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(cidr_match, &Utility::CidrMatch);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(len, &ScriptUtils::Len);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(union, &ScriptUtils::Union);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
|
||||
REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
|
||||
REGISTER_SCRIPTFUNCTION(range, &ScriptUtils::Range);
|
||||
REGISTER_SCRIPTFUNCTION(exit, &Application::Exit);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(typeof, &ScriptUtils::TypeOf);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(keys, &ScriptUtils::Keys);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(random, &Utility::Random);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_object, &ScriptUtils::GetObject);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_objects, &ScriptUtils::GetObjects);
|
||||
REGISTER_SCRIPTFUNCTION(assert, &ScriptUtils::Assert);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(string, &ScriptUtils::CastString);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(number, &ScriptUtils::CastNumber);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(bool, &ScriptUtils::CastBool);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_time, &Utility::GetTime);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(basename, &Utility::BaseName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(dirname, &Utility::DirName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(track_parents, &ScriptUtils::TrackParents);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(escape_shell_cmd, &Utility::EscapeShellCmd);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(escape_shell_arg, &Utility::EscapeShellArg);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, regex, &ScriptUtils::Regex);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, match, &Utility::Match);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, cidr_match, &Utility::CidrMatch);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, len, &ScriptUtils::Len);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, union, &ScriptUtils::Union);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, intersection, &ScriptUtils::Intersection);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, log, &ScriptUtils::Log);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, range, &ScriptUtils::Range);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, exit, &Application::Exit);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, typeof, &ScriptUtils::TypeOf);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, keys, &ScriptUtils::Keys);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, random, &Utility::Random);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_object, &ScriptUtils::GetObject);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_objects, &ScriptUtils::GetObjects);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, assert, &ScriptUtils::Assert);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, string, &ScriptUtils::CastString);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, number, &ScriptUtils::CastNumber);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, bool, &ScriptUtils::CastBool);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, get_time, &Utility::GetTime);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, basename, &Utility::BaseName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, dirname, &Utility::DirName);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, track_parents, &ScriptUtils::TrackParents);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_shell_cmd, &Utility::EscapeShellCmd);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_shell_arg, &Utility::EscapeShellArg);
|
||||
#ifdef _WIN32
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(escape_create_process_arg, &Utility::EscapeCreateProcessArg);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_create_process_arg, &Utility::EscapeCreateProcessArg);
|
||||
#endif /* _WIN32 */
|
||||
REGISTER_SCRIPTFUNCTION(ptr, &ScriptUtils::Ptr);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, ptr, &ScriptUtils::Ptr);
|
||||
|
||||
String ScriptUtils::CastString(const Value& value)
|
||||
{
|
||||
|
|
|
@ -180,6 +180,7 @@ this return T_THIS;
|
|||
globals return T_GLOBALS;
|
||||
locals return T_LOCALS;
|
||||
use return T_USE;
|
||||
__using return T_USING;
|
||||
apply return T_APPLY;
|
||||
to return T_TO;
|
||||
where return T_WHERE;
|
||||
|
|
|
@ -150,6 +150,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
|
|||
%token T_CURRENT_LINE "current_line (T_CURRENT_LINE)"
|
||||
%token T_DEBUGGER "debugger (T_DEBUGGER)"
|
||||
%token T_USE "use (T_USE)"
|
||||
%token T_USING "__using (T_USING)"
|
||||
%token T_OBJECT "object (T_OBJECT)"
|
||||
%token T_TEMPLATE "template (T_TEMPLATE)"
|
||||
%token T_INCLUDE "include (T_INCLUDE)"
|
||||
|
@ -596,6 +597,10 @@ lterm: T_LIBRARY rterm
|
|||
{
|
||||
$$ = new BreakpointExpression(@$);
|
||||
}
|
||||
| T_USING rterm
|
||||
{
|
||||
$$ = new UsingExpression($2, @$);
|
||||
}
|
||||
| apply
|
||||
| object
|
||||
| T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')'
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "config/configcompiler.hpp"
|
||||
#include "base/initialize.hpp"
|
||||
#include "base/debug.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/application.hpp"
|
||||
|
||||
#define REGISTER_CONFIG_FRAGMENT(id, name, fragment) \
|
||||
namespace { \
|
||||
|
@ -30,8 +32,13 @@
|
|||
{ \
|
||||
icinga::Expression *expression = icinga::ConfigCompiler::CompileText(name, fragment); \
|
||||
VERIFY(expression); \
|
||||
icinga::ScriptFrame frame; \
|
||||
expression->Evaluate(frame); \
|
||||
try { \
|
||||
icinga::ScriptFrame frame; \
|
||||
expression->Evaluate(frame); \
|
||||
} catch (const std::exception& ex) { \
|
||||
std::cerr << icinga::DiagnosticInformation(ex) << std::endl; \
|
||||
icinga::Application::Exit(1); \
|
||||
} \
|
||||
delete expression; \
|
||||
} \
|
||||
\
|
||||
|
|
|
@ -46,7 +46,7 @@ ConfigItem::TypeMap ConfigItem::m_Items;
|
|||
ConfigItem::ItemList ConfigItem::m_UnnamedItems;
|
||||
ConfigItem::IgnoredItemList ConfigItem::m_IgnoredItems;
|
||||
|
||||
REGISTER_SCRIPTFUNCTION_NS(Internal, run_with_activation_context, &ConfigItem::RunWithActivationContext);
|
||||
REGISTER_SCRIPTFUNCTION_NS_PREFIX(Internal, run_with_activation_context, &ConfigItem::RunWithActivationContext);
|
||||
|
||||
/**
|
||||
* Constructor for the ConfigItem class.
|
||||
|
|
|
@ -124,6 +124,8 @@ ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
|
|||
return value;
|
||||
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && static_cast<Object::Ptr>(frame.Self)->HasOwnField(m_Variable))
|
||||
return VMOps::GetField(frame.Self, m_Variable, frame.Sandboxed, m_DebugInfo);
|
||||
else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
|
||||
return value;
|
||||
else
|
||||
return ScriptGlobal::Get(m_Variable);
|
||||
}
|
||||
|
@ -142,6 +144,8 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
|
|||
|
||||
if (dhint && *dhint)
|
||||
*dhint = new DebugHint((*dhint)->GetChild(m_Variable));
|
||||
} else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
|
||||
return true;
|
||||
} else if (ScriptGlobal::Exists(m_Variable)) {
|
||||
*parent = ScriptGlobal::GetGlobals();
|
||||
|
||||
|
@ -891,3 +895,25 @@ ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint
|
|||
return Empty;
|
||||
}
|
||||
|
||||
ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
ExpressionResult importres = m_Name->Evaluate(frame);
|
||||
CHECK_RESULT(importres);
|
||||
Value import = importres.GetValue();
|
||||
|
||||
if (!import.IsObject())
|
||||
BOOST_THROW_EXCEPTION(ScriptError("The parameter does not resolve to an object", m_DebugInfo));
|
||||
|
||||
if (!frame.Imports)
|
||||
frame.Imports = new Array();
|
||||
else
|
||||
frame.Imports = static_pointer_cast<Array>(frame.Imports->Clone());
|
||||
|
||||
frame.Imports->Add(import);
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
||||
|
|
|
@ -953,6 +953,25 @@ protected:
|
|||
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
|
||||
};
|
||||
|
||||
class I2_CONFIG_API UsingExpression : public DebuggableExpression
|
||||
{
|
||||
public:
|
||||
UsingExpression(Expression *name, const DebugInfo& debugInfo = DebugInfo())
|
||||
: DebuggableExpression(debugInfo), m_Name(name)
|
||||
{ }
|
||||
|
||||
~UsingExpression(void)
|
||||
{
|
||||
delete m_Name;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
|
||||
|
||||
private:
|
||||
Expression *m_Name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* EXPRESSION_H */
|
||||
|
|
|
@ -44,15 +44,33 @@ namespace icinga
|
|||
class VMOps
|
||||
{
|
||||
public:
|
||||
static inline Value Variable(ScriptFrame& frame, const String& name, const DebugInfo& debugInfo = DebugInfo())
|
||||
static inline bool FindVarImportRef(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
|
||||
{
|
||||
Value value;
|
||||
if (frame.Locals && frame.Locals->Get(name, &value))
|
||||
return value;
|
||||
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && static_cast<Object::Ptr>(frame.Self)->HasOwnField(name))
|
||||
return GetField(frame.Self, name, frame.Sandboxed, debugInfo);
|
||||
else
|
||||
return ScriptGlobal::Get(name);
|
||||
if (!frame.Imports)
|
||||
return false;
|
||||
|
||||
ObjectLock olock(frame.Imports);
|
||||
BOOST_FOREACH(const Value& import, frame.Imports) {
|
||||
Object::Ptr obj = import;
|
||||
if (obj->HasOwnField(name)) {
|
||||
*result = import;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool FindVarImport(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
|
||||
{
|
||||
Value parent;
|
||||
|
||||
if (FindVarImportRef(frame, name, &parent, debugInfo)) {
|
||||
*result = GetField(parent, name, frame.Sandboxed, debugInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline Value ConstructorCall(const Type::Ptr& type, const std::vector<Value>& args, const DebugInfo& debugInfo = DebugInfo())
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_SCRIPTFUNCTION(get_host, &Host::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_service, &ObjectUtils::GetService);
|
||||
REGISTER_SCRIPTFUNCTION(get_user, &User::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_check_command, &CheckCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_event_command, &EventCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_notification_command, &NotificationCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_host_group, &HostGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_service_group, &ServiceGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_user_group, &UserGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION(get_time_period, &TimePeriod::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_host, &Host::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_service, &ObjectUtils::GetService);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_user, &User::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_check_command, &CheckCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_event_command, &EventCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_notification_command, &NotificationCommand::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_host_group, &HostGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_service_group, &ServiceGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_user_group, &UserGroup::GetByName);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, get_time_period, &TimePeriod::GetByName);
|
||||
|
||||
Service::Ptr ObjectUtils::GetService(const String& host, const String& name)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(PerfdataValue);
|
||||
REGISTER_SCRIPTFUNCTION(parse_performance_data, PerfdataValue::Parse);
|
||||
REGISTER_SCRIPTFUNCTION_NS(System, parse_performance_data, PerfdataValue::Parse);
|
||||
|
||||
PerfdataValue::PerfdataValue(void)
|
||||
{ }
|
||||
|
|
|
@ -215,6 +215,45 @@ static void AddSuggestion(std::vector<String>& matches, const String& word, cons
|
|||
matches.push_back(suggestion);
|
||||
}
|
||||
|
||||
static void AddSuggestions(std::vector<String>& matches, const String& word, const String& pword, const Value& value)
|
||||
{
|
||||
String prefix;
|
||||
|
||||
if (!pword.IsEmpty())
|
||||
prefix = pword + ".";
|
||||
|
||||
if (value.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr dict = value;
|
||||
|
||||
ObjectLock olock(dict);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
|
||||
AddSuggestion(matches, word, prefix + kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
Type::Ptr type = value.GetReflectionType();
|
||||
|
||||
for (int i = 0; i < type->GetFieldCount(); i++) {
|
||||
Field field = type->GetFieldInfo(i);
|
||||
|
||||
AddSuggestion(matches, word, prefix + field.Name);
|
||||
}
|
||||
|
||||
while (type) {
|
||||
Object::Ptr prototype = type->GetPrototype();
|
||||
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(prototype);
|
||||
|
||||
if (dict) {
|
||||
ObjectLock olock(dict);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
|
||||
AddSuggestion(matches, word, prefix + kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
type = type->GetBaseType();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& word, ScriptFrame& frame)
|
||||
{
|
||||
std::vector<String> matches;
|
||||
|
@ -237,6 +276,13 @@ std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& w
|
|||
}
|
||||
}
|
||||
|
||||
if (frame.Imports) {
|
||||
ObjectLock olock(frame.Imports);
|
||||
BOOST_FOREACH(const Value& import, frame.Imports) {
|
||||
AddSuggestions(matches, word, "", import);
|
||||
}
|
||||
}
|
||||
|
||||
String::SizeType cperiod = word.RFind(".");
|
||||
|
||||
if (cperiod != String::NPos) {
|
||||
|
@ -250,36 +296,8 @@ std::vector<String> ConsoleHandler::GetAutocompletionSuggestions(const String& w
|
|||
if (expr)
|
||||
value = expr->Evaluate(frame);
|
||||
|
||||
if (value.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr dict = value;
|
||||
AddSuggestions(matches, word, pword, value);
|
||||
|
||||
ObjectLock olock(dict);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
|
||||
AddSuggestion(matches, word, pword + "." + kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
Type::Ptr type = value.GetReflectionType();
|
||||
|
||||
for (int i = 0; i < type->GetFieldCount(); i++) {
|
||||
Field field = type->GetFieldInfo(i);
|
||||
|
||||
AddSuggestion(matches, word, pword + "." + field.Name);
|
||||
}
|
||||
|
||||
while (type) {
|
||||
Object::Ptr prototype = type->GetPrototype();
|
||||
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(prototype);
|
||||
|
||||
if (dict) {
|
||||
ObjectLock olock(dict);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
|
||||
AddSuggestion(matches, word, pword + "." + kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
type = type->GetBaseType();
|
||||
}
|
||||
} catch (...) { /* Ignore the exception */ }
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue