phase3: stabilize nullfix.py (disable risky local-nullable handler)

Script stable handlers (zero corruption): bang(!), late, param-nullable,
field-formal field-nullable, arg-bang. Reusable — re-run after manual fixes.
Errors: 2374(peak) -> 596 | web build: 1845 -> 571
This commit is contained in:
2026-07-26 00:15:38 +08:00
parent f1d7dbb423
commit cdaaa63d67
10 changed files with 32 additions and 12 deletions

View File

@@ -11,7 +11,7 @@ class Blog extends StatelessWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const Blog({this.key, int businessId}) : const Blog({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -16,7 +16,7 @@ class EditAddress extends StatelessWidget {
final Key? key; final Key? key;
final Address address; final Address address;
final int businessId; final int businessId;
const EditAddress(this.address, {this.key, int businessId}) : const EditAddress(this.address, {this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -11,7 +11,7 @@ class MyAddresses extends StatelessWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const MyAddresses({this.key, int businessId}) : const MyAddresses({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -11,7 +11,7 @@ class MySupport extends StatelessWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const MySupport({this.key, int businessId}) : const MySupport({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -17,7 +17,7 @@ class NewTicket extends StatefulWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const NewTicket({this.key, int businessId}) : const NewTicket({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -23,7 +23,7 @@ class DesktopEditAddress extends StatefulWidget {
final Key? key; final Key? key;
final Address address; final Address address;
final int businessId; final int businessId;
const DesktopEditAddress(this.address, {this.key, int businessId}) : const DesktopEditAddress(this.address, {this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -21,7 +21,7 @@ class DesktopNewTicket extends StatefulWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const DesktopNewTicket({this.key, int businessId}) : const DesktopNewTicket({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -21,7 +21,7 @@ class MobileEditAddress extends StatefulWidget {
final Key? key; final Key? key;
final Address address; final Address address;
final int businessId; final int businessId;
const MobileEditAddress(this.address, {this.key, int businessId}) : const MobileEditAddress(this.address, {this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -20,7 +20,7 @@ class MobileNewTicket extends StatefulWidget {
final Key? key; final Key? key;
final int businessId; final int businessId;
const MobileNewTicket({this.key, int businessId}) : const MobileNewTicket({this.key, int? businessId}) :
businessId = businessId ?? Constants.BUSINESS_ID; businessId = businessId ?? Constants.BUSINESS_ID;
@override @override

View File

@@ -33,9 +33,7 @@ PROP = re.compile(r"The property '([^']+)'")
METH = re.compile(r"The method '([^']+)'") METH = re.compile(r"The method '([^']+)'")
OPR = re.compile(r"The operator '([^']+)'") OPR = re.compile(r"The operator '([^']+)'")
NAME = re.compile(r"'([^']+)'") NAME = re.compile(r"'([^']+)'")
KEYWORDS = {'return','throw','await','yield','break','continue','assert','new','const', KEYWORDS = {'return','throw','yield','await','break','continue'}
'final','var','late','switch','case','default','if','else','for','while',
'do','try','catch','finally','in','is','as','super','this'}
def analyze(): def analyze():
out = subprocess.run(['dart','analyze','lib'], capture_output=True, text=True).stdout out = subprocess.run(['dart','analyze','lib'], capture_output=True, text=True).stdout
@@ -101,6 +99,19 @@ def insert_bang(line, col0, name, kind):
return None return None
return None return None
def make_local_nullable(lines, name, upto_line):
"""从 upto_line 向上找局部变量声明 'Type name;' 并改可空。"""
pat = re.compile(r'^(\s+)(final\s+|const\s+)?(static\s+)?([\w<>?,\s\.]+?)\s+'+re.escape(name)+r'\s*;\s*$')
for i in range(upto_line-1, -1, -1):
L=lines[i]
m=pat.match(L)
if not m: continue
indent, fmod, smod, typ = m.groups()
if typ in ('var',) or '?' in typ or '=' in L: continue
return i, f"{indent}{fmod or ''}{smod or ''}{typ}? {name};"
break
return None, None
def insert_arg_bang(line, col0): def insert_arg_bang(line, col0):
"""在参数值末尾插 '!'(仅限简单值:标识符/成员/调用/下标)。""" """在参数值末尾插 '!'(仅限简单值:标识符/成员/调用/下标)。"""
depth=0; end=None depth=0; end=None
@@ -195,6 +206,15 @@ def apply_round(errs):
new=insert_late(old) new=insert_late(old)
elif rule in ('argument_type_not_assignable','invalid_assignment'): elif rule in ('argument_type_not_assignable','invalid_assignment'):
new=insert_arg_bang(old, col-1) new=insert_arg_bang(old, col-1)
# not_assigned_potentially_non_nullable_local_variable 不自动处理
# make_local_nullable 易误改 return/throw 语句,风险高,留 IDE
elif False and rule=='not_assigned_potentially_non_nullable_local_variable':
nm=NAME.search(msg)
if nm:
fl=get(path)
fi, fnew = make_local_nullable(fl, nm.group(1), line)
if fi is not None and fl[fi]!=fnew:
fl[fi]=fnew; changed+=1
if new and new!=old: if new and new!=old:
L[line-1]=new; changed+=1 L[line-1]=new; changed+=1
flush() flush()