Skip to content

Commit

Permalink
Support assertions on static::TSomeClassTypeConst
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Jul 19, 2024
1 parent 82afad1 commit 33ed049
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 106 deletions.
7 changes: 4 additions & 3 deletions src/analyzer/expr/call/atomic_static_call_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use oxidized::{
};

use crate::{
function_analysis_data::FunctionAnalysisData, scope_analyzer::ScopeAnalyzer,
scope::BlockContext, statements_analyzer::StatementsAnalyzer,
function_analysis_data::FunctionAnalysisData, scope::BlockContext,
scope_analyzer::ScopeAnalyzer, statements_analyzer::StatementsAnalyzer,
stmt_analyzer::AnalysisError,
};

Expand Down Expand Up @@ -97,7 +97,8 @@ pub(crate) fn analyze(
}
}
TAtomic::TLiteralClassname { name } => *name,
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
let classlike_name =
if let TAtomic::TNamedObject { name, .. } = &as_type.types.first().unwrap() {
name
Expand Down
5 changes: 3 additions & 2 deletions src/analyzer/expr/call/instance_call_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::rc::Rc;
use crate::expr::expression_identifier;
use crate::expression_analyzer;
use crate::function_analysis_data::FunctionAnalysisData;
use crate::scope_analyzer::ScopeAnalyzer;
use crate::scope::BlockContext;
use crate::scope_analyzer::ScopeAnalyzer;
use crate::statements_analyzer::StatementsAnalyzer;
use crate::stmt_analyzer::AnalysisError;
use hakana_reflection_info::issue::{Issue, IssueKind};
Expand Down Expand Up @@ -122,7 +122,8 @@ pub(crate) fn analyze(
continue;
}
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
class_types.extend(&as_type.types);
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions src/analyzer/expr/call/new_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use rustc_hash::FxHashMap;
use crate::expr::call_analyzer::{check_method_args, get_generic_param_for_offset};
use crate::expression_analyzer;
use crate::function_analysis_data::FunctionAnalysisData;
use crate::scope_analyzer::ScopeAnalyzer;
use crate::scope::BlockContext;
use crate::scope_analyzer::ScopeAnalyzer;
use crate::statements_analyzer::StatementsAnalyzer;
use crate::stmt_analyzer::AnalysisError;
use hakana_reflection_info::data_flow::graph::GraphKind;
Expand Down Expand Up @@ -200,7 +200,7 @@ fn analyze_atomic(
}
}
TAtomic::TLiteralClassname { name } => *name,
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. } | TAtomic::TClassTypeConstant { as_type, .. } => {
let generic_param_type = &as_type.types[0];
if let TAtomic::TNamedObject { name, .. } = generic_param_type {
*name
Expand Down
4 changes: 3 additions & 1 deletion src/analyzer/expr/fetch/array_fetch_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,9 @@ pub(crate) fn get_array_access_type_given_offset(
} = atomic_var_type
{
atomic_var_type = as_type.get_single()
} else if let TAtomic::TGenericParam { as_type, .. } = atomic_var_type {
} else if let TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } = atomic_var_type
{
array_atomic_types.extend(&as_type.types);
continue;
}
Expand Down
24 changes: 20 additions & 4 deletions src/analyzer/expr/fetch/instance_property_fetch_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use hakana_reflection_info::issue::{Issue, IssueKind};
use hakana_reflection_info::t_atomic::TAtomic;
use hakana_reflection_info::EFFECT_READ_PROPS;
use hakana_type::{add_union_type, get_mixed_any, get_null};
use itertools::Itertools;
use oxidized::{
aast::{self, Expr},
ast_defs::Pos,
Expand Down Expand Up @@ -106,9 +107,24 @@ pub(crate) fn analyze(
let mut has_nullsafe_null = false;

if let Some(prop_name) = prop_name {
let var_atomic_types = &stmt_var_type.types;
for lhs_type_part in var_atomic_types {
if let TAtomic::TNull = lhs_type_part {
let mut var_atomic_types = stmt_var_type.types.iter().collect_vec();
while let Some(mut var_atomic_type) = var_atomic_types.pop() {
if let TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } = var_atomic_type
{
var_atomic_types.extend(&as_type.types);
continue;
}

if let TAtomic::TTypeAlias {
as_type: Some(as_type),
..
} = var_atomic_type
{
var_atomic_type = as_type.get_single();
}

if let TAtomic::TNull = var_atomic_type {
if nullsafe {
has_nullsafe_null = true;
continue;
Expand Down Expand Up @@ -136,7 +152,7 @@ pub(crate) fn analyze(
analysis_data,
context,
in_assignment,
lhs_type_part.clone(),
var_atomic_type.clone(),
&prop_name,
&stmt_var_id,
)?;
Expand Down
1 change: 1 addition & 0 deletions src/analyzer/functionlike_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,7 @@ impl<'a> FunctionLikeAnalyzer<'a> {
TAtomic::TClassTypeConstant {
class_type,
member_name,
..
} => match class_type.as_ref() {
TAtomic::TNamedObject { name, .. }
| TAtomic::TReference { name, .. } => {
Expand Down
87 changes: 42 additions & 45 deletions src/analyzer/reconciler/simple_assertion_reconciler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use hakana_reflection_info::{
use hakana_str::StrId;
use hakana_type::{
get_arraykey, get_bool, get_false, get_float, get_int, get_keyset, get_mixed_any,
get_mixed_dict, get_mixed_maybe_from_loop, get_mixed_vec, get_nothing, get_null, get_num,
get_object, get_scalar, get_string, get_true, intersect_union_types,
get_mixed_dict, get_mixed_keyset, get_mixed_maybe_from_loop, get_mixed_vec, get_nothing,
get_null, get_num, get_object, get_scalar, get_string, get_true, intersect_union_types,
template::TemplateBound,
type_comparator::{
atomic_type_comparator, type_comparison_result::TypeComparisonResult, union_type_comparator,
Expand Down Expand Up @@ -466,13 +466,12 @@ pub(crate) fn intersect_null(
TAtomic::TNull => {
acceptable_types.push(TAtomic::TNull);
}
TAtomic::TMixed
| TAtomic::TMixedWithFlags(_, false, _, false)
| TAtomic::TClassTypeConstant { .. } => {
TAtomic::TMixed | TAtomic::TMixedWithFlags(_, false, _, false) => {
acceptable_types.push(TAtomic::TNull);
did_remove_type = true;
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_null());

Expand Down Expand Up @@ -659,7 +658,8 @@ fn intersect_vec(
TAtomic::TVec { .. } => {
acceptable_types.push(atomic.clone());
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_mixed_vec());

Expand All @@ -682,21 +682,12 @@ fn intersect_vec(

did_remove_type = true;
}
TAtomic::TClassTypeConstant { .. } => {
acceptable_types.push(TAtomic::TVec {
known_items: None,
type_param: Box::new(get_mixed_any()),
non_empty: false,
known_count: None,
});
did_remove_type = true;
}
TAtomic::TTypeVariable { name } => {
if let Some(pos) = pos {
if let Some((lower_bounds, _)) =
analysis_data.type_variable_bounds.get_mut(name)
{
let mut bound = TemplateBound::new(get_mixed_dict(), 0, None, None);
let mut bound = TemplateBound::new(get_mixed_vec(), 0, None, None);
bound.pos = Some(statements_analyzer.get_hpos(pos));
lower_bounds.push(bound);
}
Expand Down Expand Up @@ -795,8 +786,28 @@ fn intersect_keyset(
TAtomic::TKeyset { .. } => {
acceptable_types.push(atomic.clone());
}
TAtomic::TClassTypeConstant { .. } => {
acceptable_types.push(atomic.clone());
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_mixed_keyset());

acceptable_types.push(atomic);
} else {
let atomic = atomic.replace_template_extends(intersect_keyset(
assertion,
as_type,
None,
false,
analysis_data,
statements_analyzer,
pos,
calling_functionlike_id,
is_equality,
suppressed_issues,
));
acceptable_types.push(atomic);
}

did_remove_type = true;
}
TAtomic::TNamedObject {
Expand Down Expand Up @@ -881,7 +892,8 @@ fn intersect_dict(
TAtomic::TDict { .. } => {
acceptable_types.push(atomic.clone());
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_mixed_dict());

Expand All @@ -904,15 +916,6 @@ fn intersect_dict(

did_remove_type = true;
}
TAtomic::TClassTypeConstant { .. } => {
acceptable_types.push(TAtomic::TDict {
known_items: None,
params: Some((Box::new(get_arraykey(true)), Box::new(get_mixed_any()))),
non_empty: false,
shape_name: None,
});
did_remove_type = true;
}
TAtomic::TTypeVariable { name } => {
if let Some(pos) = pos {
if let Some((lower_bounds, _)) =
Expand Down Expand Up @@ -1153,10 +1156,6 @@ fn intersect_string(
| TAtomic::TArraykey { .. } => {
return get_string();
}
TAtomic::TClassTypeConstant { .. } => {
acceptable_types.push(TAtomic::TString);
did_remove_type = true;
}
TAtomic::TEnumLiteralCase {
constraint_type, ..
} => {
Expand All @@ -1176,7 +1175,8 @@ fn intersect_string(
return get_string();
}
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_string());

Expand Down Expand Up @@ -1303,7 +1303,8 @@ fn intersect_int(
| TAtomic::TMixedFromLoopIsset => {
return get_int();
}
TAtomic::TGenericParam { as_type, .. } => {
TAtomic::TGenericParam { as_type, .. }
| TAtomic::TClassTypeConstant { as_type, .. } => {
if as_type.is_mixed() {
let atomic = atomic.replace_template_extends(get_int());

Expand All @@ -1327,10 +1328,6 @@ fn intersect_int(

did_remove_type = true;
}
TAtomic::TClassTypeConstant { .. } => {
acceptable_types.push(TAtomic::TInt);
did_remove_type = true;
}
TAtomic::TTypeVariable { name } => {
if let Some(pos) = pos {
if let Some((lower_bounds, _)) =
Expand Down Expand Up @@ -2005,7 +2002,8 @@ fn reconcile_has_array_key(
did_remove_type = true;
}
}
TAtomic::TGenericParam { ref as_type, .. } => {
TAtomic::TGenericParam { ref as_type, .. }
| TAtomic::TClassTypeConstant { ref as_type, .. } => {
if as_type.is_mixed() {
acceptable_types.push(atomic);
} else {
Expand Down Expand Up @@ -2034,8 +2032,7 @@ fn reconcile_has_array_key(
TAtomic::TMixed
| TAtomic::TMixedWithFlags(..)
| TAtomic::TMixedFromLoopIsset
| TAtomic::TTypeAlias { .. }
| TAtomic::TClassTypeConstant { .. } => {
| TAtomic::TTypeAlias { .. } => {
did_remove_type = true;
acceptable_types.push(atomic);
}
Expand Down Expand Up @@ -2260,7 +2257,8 @@ fn reconcile_has_nonnull_entry_for_key(
did_remove_type = true;
}
}
TAtomic::TGenericParam { ref as_type, .. } => {
TAtomic::TGenericParam { ref as_type, .. }
| TAtomic::TClassTypeConstant { ref as_type, .. } => {
if as_type.is_mixed() {
acceptable_types.push(atomic);
} else {
Expand Down Expand Up @@ -2290,8 +2288,7 @@ fn reconcile_has_nonnull_entry_for_key(
TAtomic::TMixed
| TAtomic::TMixedWithFlags(..)
| TAtomic::TMixedFromLoopIsset
| TAtomic::TTypeAlias { .. }
| TAtomic::TClassTypeConstant { .. } => {
| TAtomic::TTypeAlias { .. } => {
did_remove_type = true;
acceptable_types.push(atomic);
}
Expand Down
Loading

0 comments on commit 33ed049

Please sign in to comment.