luaur_analysis/methods/
error_converter_operator_call_error.rs1use crate::enums::context_error::Context;
2use crate::functions::follow_type::follow_type_id;
3use crate::functions::get_definition_module_name::get_definition_module_name;
4use crate::functions::get_type_alt_j::get_type_id;
5use crate::functions::to_string_error_alt_k::to_string_type_error_type_error_to_string_options;
6use crate::functions::to_string_to_string_alt_c::to_string_type_id;
7use crate::records::error_converter::ErrorConverter;
8use crate::records::never_type::NeverType;
9use crate::records::type_error_to_string_options::TypeErrorToStringOptions;
10use crate::records::type_mismatch::TypeMismatch;
11use alloc::string::String;
12
13impl ErrorConverter {
14 pub fn operator_call_40(&self, tm: &TypeMismatch) -> String {
15 let given_type_name = to_string_type_id(tm.given_type);
16 let wanted_type_name = to_string_type_id(tm.wanted_type);
17
18 let mut result = String::new();
19
20 let quote = |s: &str| -> String { format!("'{}'", s) };
21
22 let construct_error_message = |given_type: String,
23 wanted_type: String,
24 given_module: Option<String>,
25 wanted_module: Option<String>|
26 -> String {
27 let given = if let Some(ref gm) = given_module {
28 format!("{} from {}", quote(&given_type), quote(gm))
29 } else {
30 quote(&given_type)
31 };
32
33 let wanted = if let Some(ref wm) = wanted_module {
34 format!("{} from {}", quote(&wanted_type), quote(wm))
35 } else {
36 quote(&wanted_type)
37 };
38
39 let luau_indent_type_mismatch_max_type_length =
40 luaur_common::FInt::LuauIndentTypeMismatchMaxTypeLength.get() as usize;
41
42 let follow_wanted = unsafe { follow_type_id(tm.wanted_type) };
43 let wanted_never = unsafe { get_type_id::<NeverType>(follow_wanted) };
44 if !wanted_never.is_null() {
45 if given_type.len() <= luau_indent_type_mismatch_max_type_length {
46 return format!("Expected this to be unreachable, but got {}", given);
47 } else {
48 return format!("Expected this to be unreachable, but got\n\t{}", given);
49 }
50 }
51
52 if tm.context == Context::InvariantContext {
53 if given_type.len() <= luau_indent_type_mismatch_max_type_length
54 || wanted_type.len() <= luau_indent_type_mismatch_max_type_length
55 {
56 return format!("Expected this to be exactly {}, but got {}", wanted, given);
57 } else {
58 return format!(
59 "Expected this to be exactly\n\t{}\nbut got\n\t{}",
60 wanted, given
61 );
62 }
63 }
64
65 if given_type.len() <= luau_indent_type_mismatch_max_type_length
66 || wanted_type.len() <= luau_indent_type_mismatch_max_type_length
67 {
68 return format!("Expected this to be {}, but got {}", wanted, given);
69 } else {
70 return format!("Expected this to be\n\t{}\nbut got\n\t{}", wanted, given);
71 }
72 };
73
74 if given_type_name == wanted_type_name {
75 let given_definition_module = get_definition_module_name(tm.given_type);
76 let wanted_definition_module = get_definition_module_name(tm.wanted_type);
77
78 if let (Some(ref given_mod), Some(ref wanted_mod)) =
79 (given_definition_module, wanted_definition_module)
80 {
81 if !self.file_resolver.is_null() {
82 let given_module_name = unsafe {
83 crate::records::file_resolver::FileResolver::get_human_readable_module_name(
84 self.file_resolver,
85 given_mod,
86 )
87 };
88 let wanted_module_name = unsafe {
89 crate::records::file_resolver::FileResolver::get_human_readable_module_name(
90 self.file_resolver,
91 wanted_mod,
92 )
93 };
94
95 result = construct_error_message(
96 given_type_name.clone(),
97 wanted_type_name.clone(),
98 Some(given_module_name),
99 Some(wanted_module_name),
100 );
101 } else {
102 result = construct_error_message(
103 given_type_name.clone(),
104 wanted_type_name.clone(),
105 Some(given_mod.clone()),
106 Some(wanted_mod.clone()),
107 );
108 }
109 }
110 }
111
112 if result.is_empty() {
113 result = construct_error_message(
114 given_type_name.clone(),
115 wanted_type_name.clone(),
116 None,
117 None,
118 );
119 }
120
121 if let Some(ref err) = tm.error {
122 result.push_str("\ncaused by:\n ");
123
124 if !tm.reason.is_empty() {
125 result.push_str(&tm.reason);
126 result.push('\n');
127 }
128
129 let opts = TypeErrorToStringOptions {
130 file_resolver: self.file_resolver,
131 };
132 result.push_str(&to_string_type_error_type_error_to_string_options(
133 err, opts,
134 ));
135 } else if !tm.reason.is_empty() {
136 result.push_str("; ");
137 result.push_str(&tm.reason);
138 }
139
140 result
141 }
142}