mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-10 04:40:25 +01:00
b5d3c6c9a5
Copied from Gut repo godot_4 branch commit: ba19a4c1b6f88160641a67a39729144046c6391f
233 lines
No EOL
6.7 KiB
GDScript
233 lines
No EOL
6.7 KiB
GDScript
# -------------
|
|
# returns{} and parameters {} have the followin structure
|
|
# -------------
|
|
# {
|
|
# inst_id_or_path1:{
|
|
# method_name1: [StubParams, StubParams],
|
|
# method_name2: [StubParams, StubParams]
|
|
# },
|
|
# inst_id_or_path2:{
|
|
# method_name1: [StubParams, StubParams],
|
|
# method_name2: [StubParams, StubParams]
|
|
# }
|
|
# }
|
|
var returns = {}
|
|
var _utils = load('res://addons/gut/utils.gd').get_instance()
|
|
var _lgr = _utils.get_logger()
|
|
var _strutils = _utils.Strutils.new()
|
|
var _class_db_name_hash = {}
|
|
|
|
func _init():
|
|
_class_db_name_hash = _make_crazy_dynamic_over_engineered_class_db_hash()
|
|
|
|
# So, I couldn't figure out how to get to a reference for a GDNative Class
|
|
# using a string. ClassDB has all thier names...so I made a hash using those
|
|
# names and the classes. Then I dynmaically make a script that has that as
|
|
# the source and grab the hash out of it and return it. Super Rube Golbergery,
|
|
# but tons of fun.
|
|
func _make_crazy_dynamic_over_engineered_class_db_hash():
|
|
var text = "var all_the_classes = {\n"
|
|
for classname in ClassDB.get_class_list():
|
|
if(ClassDB.can_instantiate(classname)):
|
|
text += str('"', classname, '": ', classname, ", \n")
|
|
else:
|
|
text += str('# ', classname, "\n")
|
|
text += "}"
|
|
var inst = _utils.create_script_from_source(text).new()
|
|
return inst.all_the_classes
|
|
|
|
|
|
func _find_matches(obj, method):
|
|
var matches = null
|
|
var last_not_null_parent = null
|
|
|
|
# Search for what is passed in first. This could be a class or an instance.
|
|
# We want to find the instance before we find the class. If we do not have
|
|
# an entry for the instance then see if we have an entry for the class.
|
|
if(returns.has(obj) and returns[obj].has(method)):
|
|
matches = returns[obj][method]
|
|
elif(_utils.is_instance(obj)):
|
|
var parent = obj.get_script()
|
|
var found = false
|
|
while(parent != null and !found):
|
|
found = returns.has(parent)
|
|
|
|
if(!found):
|
|
last_not_null_parent = parent
|
|
parent = parent.get_base_script()
|
|
|
|
# Could not find the script so check to see if a native class of this
|
|
# type was stubbed.
|
|
if(!found):
|
|
var base_type = last_not_null_parent.get_instance_base_type()
|
|
if(_class_db_name_hash.has(base_type)):
|
|
parent = _class_db_name_hash[base_type]
|
|
found = returns.has(parent)
|
|
|
|
if(found and returns[parent].has(method)):
|
|
matches = returns[parent][method]
|
|
|
|
return matches
|
|
|
|
|
|
# Searches returns for an entry that matches the instance or the class that
|
|
# passed in obj is.
|
|
#
|
|
# obj can be an instance, class, or a path.
|
|
func _find_stub(obj, method, parameters=null, find_overloads=false):
|
|
var to_return = null
|
|
var matches = _find_matches(obj, method)
|
|
|
|
if(matches == null):
|
|
return null
|
|
|
|
var param_match = null
|
|
var null_match = null
|
|
var overload_match = null
|
|
|
|
for i in range(matches.size()):
|
|
var cur_stub = matches[i]
|
|
if(cur_stub.parameters == parameters):
|
|
param_match = cur_stub
|
|
|
|
if(cur_stub.parameters == null and !cur_stub.is_param_override_only()):
|
|
null_match = cur_stub
|
|
|
|
if(cur_stub.has_param_override()):
|
|
if(overload_match == null || overload_match.is_script_default):
|
|
overload_match = cur_stub
|
|
|
|
if(find_overloads and overload_match != null):
|
|
to_return = overload_match
|
|
# We have matching parameter values so return the stub value for that
|
|
elif(param_match != null):
|
|
to_return = param_match
|
|
# We found a case where the parameters were not specified so return
|
|
# parameters for that. Only do this if the null match is not *just*
|
|
# a paramerter override stub.
|
|
elif(null_match != null):
|
|
to_return = null_match
|
|
|
|
return to_return
|
|
|
|
|
|
|
|
# ##############
|
|
# Public
|
|
# ##############
|
|
|
|
func add_stub(stub_params):
|
|
stub_params._lgr = _lgr
|
|
var key = stub_params.stub_target
|
|
|
|
if(!returns.has(key)):
|
|
returns[key] = {}
|
|
|
|
if(!returns[key].has(stub_params.stub_method)):
|
|
returns[key][stub_params.stub_method] = []
|
|
|
|
returns[key][stub_params.stub_method].append(stub_params)
|
|
|
|
|
|
# Gets a stubbed return value for the object and method passed in. If the
|
|
# instance was stubbed it will use that, otherwise it will use the path and
|
|
# subpath of the object to try to find a value.
|
|
#
|
|
# It will also use the optional list of parameter values to find a value. If
|
|
# the object was stubbed with no parameters than any parameters will match.
|
|
# If it was stubbed with specific parameter values then it will try to match.
|
|
# If the parameters do not match BUT there was also an empty parameter list stub
|
|
# then it will return those.
|
|
# If it cannot find anything that matches then null is returned.for
|
|
#
|
|
# Parameters
|
|
# obj: this should be an instance of a doubled object.
|
|
# method: the method called
|
|
# parameters: optional array of parameter vales to find a return value for.
|
|
func get_return(obj, method, parameters=null):
|
|
var stub_info = _find_stub(obj, method, parameters)
|
|
|
|
if(stub_info != null):
|
|
return stub_info.return_val
|
|
else:
|
|
_lgr.warn(str('Call to [', method, '] was not stubbed for the supplied parameters ', parameters, '. Null was returned.'))
|
|
return null
|
|
|
|
|
|
func should_call_super(obj, method, parameters=null):
|
|
if(_utils.non_super_methods.has(method)):
|
|
return false
|
|
|
|
var stub_info = _find_stub(obj, method, parameters)
|
|
|
|
var is_partial = false
|
|
if(typeof(obj) != TYPE_STRING): # some stubber tests test with strings
|
|
is_partial = obj.__gutdbl.is_partial
|
|
var should = is_partial
|
|
|
|
if(stub_info != null):
|
|
should = stub_info.call_super
|
|
elif(!is_partial):
|
|
# this log message is here because of how the generated doubled scripts
|
|
# are structured. With this log msg here, you will only see one
|
|
# "unstubbed" info instead of multiple.
|
|
_lgr.info('Unstubbed call to ' + method + '::' + _strutils.type2str(obj))
|
|
should = false
|
|
|
|
return should
|
|
|
|
|
|
func get_parameter_count(obj, method):
|
|
var to_return = null
|
|
var stub_info = _find_stub(obj, method, null, true)
|
|
|
|
if(stub_info != null and stub_info.has_param_override()):
|
|
to_return = stub_info.parameter_count
|
|
|
|
return to_return
|
|
|
|
|
|
func get_default_value(obj, method, p_index):
|
|
var to_return = null
|
|
var stub_info = _find_stub(obj, method, null, true)
|
|
|
|
if(stub_info != null and
|
|
stub_info.parameter_defaults != null and
|
|
stub_info.parameter_defaults.size() > p_index):
|
|
|
|
to_return = stub_info.parameter_defaults[p_index]
|
|
|
|
return to_return
|
|
|
|
|
|
func clear():
|
|
returns.clear()
|
|
|
|
|
|
func get_logger():
|
|
return _lgr
|
|
|
|
|
|
func set_logger(logger):
|
|
_lgr = logger
|
|
|
|
|
|
func to_s():
|
|
var text = ''
|
|
for thing in returns:
|
|
text += str("-- ", thing, " --\n")
|
|
for method in returns[thing]:
|
|
text += str("\t", method, "\n")
|
|
for i in range(returns[thing][method].size()):
|
|
text += "\t\t" + returns[thing][method][i].to_s() + "\n"
|
|
|
|
if(text == ''):
|
|
text = 'Stubber is empty';
|
|
|
|
return text
|
|
|
|
|
|
func stub_defaults_from_meta(target, method_meta):
|
|
var params = _utils.StubParams.new(target, method_meta)
|
|
params.is_script_default = true
|
|
add_stub(params) |