From 8ff98695468defca9a0e5f3bd21ec0f4b91f2a73 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Thu, 8 Aug 2024 18:31:52 +0300 Subject: [PATCH] new inspection for string nullability --- src/linter/quickfix.go | 8 ++++++++ src/linter/report.go | 9 +++++++++ src/linter/root_checker.go | 18 +++++++++++++++++- .../quickfix/stringNullable.fix.expected | 5 +++++ .../testdata/quickfix/stringNullable.php | 5 +++++ 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/tests/golden/testdata/quickfix/stringNullable.fix.expected create mode 100644 src/tests/golden/testdata/quickfix/stringNullable.php diff --git a/src/linter/quickfix.go b/src/linter/quickfix.go index ef83aa8a..f2452e14 100644 --- a/src/linter/quickfix.go +++ b/src/linter/quickfix.go @@ -47,6 +47,14 @@ func (g *QuickFixGenerator) NullForNotNullableProperty(prop *ir.PropertyStmt) qu } } +func (g *QuickFixGenerator) NullableStringType(param *ir.Name) quickfix.TextEdit { + return quickfix.TextEdit{ + StartPos: param.Position.StartPos, + EndPos: param.Position.EndPos, + Replacement: "?string", + } +} + func (g *QuickFixGenerator) GetType(node ir.Node, isFunctionName, nodeText string, isNegative bool) quickfix.TextEdit { pos := ir.GetPosition(node) diff --git a/src/linter/report.go b/src/linter/report.go index d1914da3..3f64ac82 100644 --- a/src/linter/report.go +++ b/src/linter/report.go @@ -25,6 +25,15 @@ func addBuiltinCheckers(reg *CheckersRegistry) { After: `$s = strip_tags($s, '
')`, }, + { + Name: "nullableString", + Default: true, + Quickfix: true, + Comment: "Report not nullable string can be null.", + Before: `function f(string $str = null);`, + After: `function f(?string $str = null);`, + }, + { Name: "emptyStmt", Default: true, diff --git a/src/linter/root_checker.go b/src/linter/root_checker.go index 149b767d..fc22f660 100644 --- a/src/linter/root_checker.go +++ b/src/linter/root_checker.go @@ -604,8 +604,24 @@ func (r *rootChecker) checkFuncParam(p *ir.Parameter) { } return true }) - r.CheckTypeHintFunctionParam(p) + r.CheckParamStringNullability(p) +} + +func (r *rootChecker) CheckParamStringNullability(p *ir.Parameter) { + if param, ok := p.VariableType.(*ir.Name); ok { + if param.Value != "string" { + return + } + + if defValue, ok := p.DefaultValue.(*ir.ConstFetchExpr); ok { + if defValue.Constant.Value != "null" { + return + } + r.walker.Report(param, LevelWarning, "nullableString", "string with null default value should be explicitly nullable") + r.walker.addQuickFix("nullableString", r.quickfix.NullableStringType(param)) + } + } } func (r *rootChecker) CheckTypeHintFunctionParam(p *ir.Parameter) { diff --git a/src/tests/golden/testdata/quickfix/stringNullable.fix.expected b/src/tests/golden/testdata/quickfix/stringNullable.fix.expected new file mode 100644 index 00000000..d7134cda --- /dev/null +++ b/src/tests/golden/testdata/quickfix/stringNullable.fix.expected @@ -0,0 +1,5 @@ +