summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript_parser.h
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_parser.h')
-rw-r--r--modules/gdscript/gdscript_parser.h120
1 files changed, 78 insertions, 42 deletions
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 4b46b98baa..7fb9ffe9a5 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -101,11 +101,9 @@ public:
struct WhileNode;
class DataType {
- private:
- // Private access so we can control memory management.
- DataType *container_element_type = nullptr;
-
public:
+ Vector<DataType> container_element_types;
+
enum Kind {
BUILTIN,
NATIVE,
@@ -152,24 +150,39 @@ public:
_FORCE_INLINE_ String to_string_strict() const { return is_hard_type() ? to_string() : "Variant"; }
PropertyInfo to_property_info(const String &p_name) const;
- _FORCE_INLINE_ void set_container_element_type(const DataType &p_type) {
- container_element_type = memnew(DataType(p_type));
+ _FORCE_INLINE_ static DataType get_variant_type() { // Default DataType for container elements.
+ DataType datatype;
+ datatype.kind = VARIANT;
+ datatype.type_source = INFERRED;
+ return datatype;
}
- _FORCE_INLINE_ DataType get_container_element_type() const {
- ERR_FAIL_NULL_V(container_element_type, DataType());
- return *container_element_type;
+ _FORCE_INLINE_ void set_container_element_type(int p_index, const DataType &p_type) {
+ ERR_FAIL_COND(p_index < 0);
+ while (p_index >= container_element_types.size()) {
+ container_element_types.push_back(get_variant_type());
+ }
+ container_element_types.write[p_index] = DataType(p_type);
}
- _FORCE_INLINE_ bool has_container_element_type() const {
- return container_element_type != nullptr;
+ _FORCE_INLINE_ DataType get_container_element_type(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, container_element_types.size(), get_variant_type());
+ return container_element_types[p_index];
}
- _FORCE_INLINE_ void unset_container_element_type() {
- if (container_element_type) {
- memdelete(container_element_type);
- };
- container_element_type = nullptr;
+ _FORCE_INLINE_ DataType get_container_element_type_or_variant(int p_index) const {
+ if (p_index < 0 || p_index >= container_element_types.size()) {
+ return get_variant_type();
+ }
+ return container_element_types[p_index];
+ }
+
+ _FORCE_INLINE_ bool has_container_element_type(int p_index) const {
+ return p_index >= 0 && p_index < container_element_types.size();
+ }
+
+ _FORCE_INLINE_ bool has_container_element_types() const {
+ return !container_element_types.is_empty();
}
bool is_typed_container_type() const;
@@ -210,7 +223,7 @@ public:
}
bool operator!=(const DataType &p_other) const {
- return !(this->operator==(p_other));
+ return !(*this == p_other);
}
void operator=(const DataType &p_other) {
@@ -229,10 +242,7 @@ public:
class_type = p_other.class_type;
method_info = p_other.method_info;
enum_values = p_other.enum_values;
- unset_container_element_type();
- if (p_other.has_container_element_type()) {
- set_container_element_type(p_other.get_container_element_type());
- }
+ container_element_types = p_other.container_element_types;
}
DataType() = default;
@@ -241,9 +251,7 @@ public:
*this = p_other;
}
- ~DataType() {
- unset_container_element_type();
- }
+ ~DataType() {}
};
struct ParserError {
@@ -266,13 +274,17 @@ public:
String description;
Vector<Pair<String, String>> tutorials;
bool is_deprecated = false;
+ String deprecated_message;
bool is_experimental = false;
+ String experimental_message;
};
struct MemberDocData {
String description;
bool is_deprecated = false;
+ String deprecated_message;
bool is_experimental = false;
+ String experimental_message;
};
#endif // TOOLS_ENABLED
@@ -326,9 +338,6 @@ public:
int leftmost_column = 0, rightmost_column = 0;
Node *next = nullptr;
List<AnnotationNode *> annotations;
-#ifdef DEBUG_ENABLED
- Vector<GDScriptWarning::Code> ignored_warnings;
-#endif
DataType datatype;
@@ -489,6 +498,7 @@ public:
Vector<ExpressionNode *> arguments;
StringName function_name;
bool is_super = false;
+ bool is_static = false;
CallNode() {
type = CALL;
@@ -765,7 +775,7 @@ public:
bool has_function(const StringName &p_name) const {
return has_member(p_name) && members[members_indices[p_name]].type == Member::FUNCTION;
}
- template <class T>
+ template <typename T>
void add_member(T *p_member_node) {
members_indices[p_member_node->identifier->name] = members.size();
members.push_back(Member(p_member_node));
@@ -888,9 +898,10 @@ public:
union {
ParameterNode *parameter_source = nullptr;
- ConstantNode *constant_source;
- VariableNode *variable_source;
IdentifierNode *bind_source;
+ VariableNode *variable_source;
+ ConstantNode *constant_source;
+ SignalNode *signal_source;
};
FunctionNode *source_function = nullptr;
@@ -1039,6 +1050,8 @@ public:
MemberDocData doc_data;
#endif // TOOLS_ENABLED
+ int usages = 0;
+
SignalNode() {
type = SIGNAL;
}
@@ -1155,7 +1168,7 @@ public:
bool has_local(const StringName &p_name) const;
const Local &get_local(const StringName &p_name) const;
- template <class T>
+ template <typename T>
void add_local(T *p_local, FunctionNode *p_source_function) {
locals_indices[p_local->identifier->name] = locals.size();
locals.push_back(Local(p_local, p_source_function));
@@ -1183,7 +1196,11 @@ public:
struct TypeNode : public Node {
Vector<IdentifierNode *> type_chain;
- TypeNode *container_type = nullptr;
+ Vector<TypeNode *> container_types;
+
+ TypeNode *get_container_type_or_null(int p_index) const {
+ return p_index >= 0 && p_index < container_types.size() ? container_types[p_index] : nullptr;
+ }
TypeNode() {
type = TYPE;
@@ -1304,6 +1321,7 @@ public:
private:
friend class GDScriptAnalyzer;
+ friend class GDScriptParserRef;
bool _is_tool = false;
String script_path;
@@ -1312,19 +1330,28 @@ private:
bool can_break = false;
bool can_continue = false;
List<bool> multiline_stack;
+ HashMap<String, Ref<GDScriptParserRef>> depended_parsers;
ClassNode *head = nullptr;
Node *list = nullptr;
List<ParserError> errors;
#ifdef DEBUG_ENABLED
+ struct PendingWarning {
+ const Node *source = nullptr;
+ GDScriptWarning::Code code = GDScriptWarning::WARNING_MAX;
+ bool treated_as_error = false;
+ Vector<String> symbols;
+ };
+
bool is_ignoring_warnings = false;
List<GDScriptWarning> warnings;
- HashSet<GDScriptWarning::Code> ignored_warnings;
+ List<PendingWarning> pending_warnings;
+ HashSet<int> warning_ignored_lines[GDScriptWarning::WARNING_MAX];
HashSet<int> unsafe_lines;
#endif
- GDScriptTokenizer tokenizer;
+ GDScriptTokenizer *tokenizer = nullptr;
GDScriptTokenizer::Token previous;
GDScriptTokenizer::Token current;
@@ -1352,13 +1379,13 @@ private:
FUNCTION = 1 << 5,
STATEMENT = 1 << 6,
STANDALONE = 1 << 7,
- CLASS_LEVEL = CLASS | VARIABLE | FUNCTION,
+ CLASS_LEVEL = CLASS | VARIABLE | CONSTANT | SIGNAL | FUNCTION,
};
uint32_t target_kind = 0; // Flags.
AnnotationAction apply = nullptr;
MethodInfo info;
};
- HashMap<StringName, AnnotationInfo> valid_annotations;
+ static HashMap<StringName, AnnotationInfo> valid_annotations;
List<AnnotationNode *> annotation_stack;
typedef ExpressionNode *(GDScriptParser::*ParseFunction)(ExpressionNode *p_previous_operand, bool p_can_assign);
@@ -1402,7 +1429,9 @@ private:
void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
void reset_extents(Node *p_node, Node *p_from);
- template <class T>
+ HashSet<String> dependencies;
+
+ template <typename T>
T *alloc_node() {
T *node = memnew(T);
@@ -1422,6 +1451,7 @@ private:
void push_warning(const Node *p_source, GDScriptWarning::Code p_code, const Symbols &...p_symbols) {
push_warning(p_source, p_code, Vector<String>{ p_symbols... });
}
+ void apply_pending_warnings();
#endif
void make_completion_context(CompletionType p_type, Node *p_node, int p_argument = -1, bool p_force = false);
@@ -1448,7 +1478,7 @@ private:
void parse_class_name();
void parse_extends();
void parse_class_body(bool p_is_multiline);
- template <class T>
+ template <typename T>
void parse_class_member(T *(GDScriptParser::*p_parse_function)(bool), AnnotationInfo::TargetKind p_target, const String &p_member_kind, bool p_is_static = false);
SignalNode *parse_signal(bool p_is_static);
EnumNode *parse_enum(bool p_is_static);
@@ -1458,7 +1488,7 @@ private:
SuiteNode *parse_suite(const String &p_context, SuiteNode *p_suite = nullptr, bool p_for_lambda = false);
// Annotations
AnnotationNode *parse_annotation(uint32_t p_valid_targets);
- bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false);
+ static bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false);
bool validate_annotation_arguments(AnnotationNode *p_annotation);
void clear_unused_annotations();
bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
@@ -1466,6 +1496,7 @@ private:
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyHint t_hint, Variant::Type t_type>
bool export_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
+ bool export_custom_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyUsageFlags t_usage>
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
@@ -1528,8 +1559,11 @@ private:
public:
Error parse(const String &p_source_code, const String &p_script_path, bool p_for_completion);
+ Error parse_binary(const Vector<uint8_t> &p_binary, const String &p_script_path);
ClassNode *get_tree() const { return head; }
bool is_tool() const { return _is_tool; }
+ Ref<GDScriptParserRef> get_depended_parser_for(const String &p_path);
+ const HashMap<String, Ref<GDScriptParserRef>> &get_depended_parsers();
ClassNode *find_class(const String &p_qualified_name) const;
bool has_class(const GDScriptParser::ClassNode *p_class) const;
static Variant::Type get_builtin_type(const StringName &p_type); // Excluding `Variant::NIL` and `Variant::OBJECT`.
@@ -1540,9 +1574,11 @@ public:
bool annotation_exists(const String &p_annotation_name) const;
const List<ParserError> &get_errors() const { return errors; }
- const List<String> get_dependencies() const {
- // TODO: Keep track of deps.
- return List<String>();
+ const HashSet<String> &get_dependencies() const {
+ return dependencies;
+ }
+ void add_dependency(const String &p_dependency) {
+ dependencies.insert(p_dependency);
}
#ifdef DEBUG_ENABLED
const List<GDScriptWarning> &get_warnings() const { return warnings; }