From 433b4fa3c87adbbd6aa753930fa3f4cf4bbce667 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 14 May 2026 13:36:58 -0700 Subject: [PATCH] analyzer: Consider "Immutable" annotations the same as "immutable" Fixes https://github.com/dart-lang/sdk/issues/57670 Change-Id: I5a9ecd153c4e4de21e00860a7743f946096b0849 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/503680 Commit-Queue: Samuel Rawlins Reviewed-by: Konstantin Shcheglov --- pkg/analyzer/lib/src/dart/element/element.dart | 12 +++++++++++- ...efer_const_constructors_in_immutables_test.dart | 13 +++++++++++++ ...r_const_literals_to_create_immutables_test.dart | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index f092ba802fd..06f96f54544 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -1564,6 +1564,10 @@ class ElementAnnotationImpl /// factory. static const String _factoryVariableName = 'factory'; + /// The name of the class used to mark a class and its subclasses as being + /// immutable. + static const String _immutableClassName = 'Immutable'; + /// The name of the top-level variable used to mark a class and its subclasses /// as being immutable. static const String _immutableVariableName = 'immutable'; @@ -1793,7 +1797,9 @@ class ElementAnnotationImpl bool get isFactory => _isPackageMetaGetter(_factoryVariableName); @override - bool get isImmutable => _isPackageMetaGetter(_immutableVariableName); + bool get isImmutable => + _isPackageMetaGetter(_immutableVariableName) || + _isPackageMetaConstructor(_immutableClassName); @override bool get isInternal => _isPackageMetaGetter(_internalVariableName); @@ -1949,6 +1955,10 @@ class ElementAnnotationImpl return _isTopGetter(libraryName: 'dart.core', name: name); } + bool _isPackageMetaConstructor(String className) { + return _isConstructor(libraryName: _metaLibName, className: className); + } + bool _isPackageMetaGetter(String name) { return _isTopGetter(libraryName: _metaLibName, name: name); } diff --git a/pkg/linter/test/rules/prefer_const_constructors_in_immutables_test.dart b/pkg/linter/test/rules/prefer_const_constructors_in_immutables_test.dart index 20de0861af6..1108827f3be 100644 --- a/pkg/linter/test/rules/prefer_const_constructors_in_immutables_test.dart +++ b/pkg/linter/test/rules/prefer_const_constructors_in_immutables_test.dart @@ -490,6 +490,19 @@ class C { ); } + test_immutableInstantiation_nonConstConstructor() async { + await assertDiagnostics( + r''' +import 'package:meta/meta.dart'; +@Immutable('') +class A { + A(); +} +''', + [lint(60, 1)], + ); + } + test_implementsImmutable() async { await assertNoDiagnostics(r''' import 'package:meta/meta.dart'; diff --git a/pkg/linter/test/rules/prefer_const_literals_to_create_immutables_test.dart b/pkg/linter/test/rules/prefer_const_literals_to_create_immutables_test.dart index 7bd29161666..d847c183305 100644 --- a/pkg/linter/test/rules/prefer_const_literals_to_create_immutables_test.dart +++ b/pkg/linter/test/rules/prefer_const_literals_to_create_immutables_test.dart @@ -108,6 +108,20 @@ var x = C([]); ); } + test_listLiteral_noConst_instantiationAnnotation() async { + await assertDiagnostics( + r''' +import 'package:meta/meta.dart'; +@Immutable('') +class C { + const C(List p); +} +var x = C([]); +''', + [lint(97, 2)], + ); + } + test_listLiteral_notConstable_noConst() async { await assertNoDiagnostics(r''' import 'package:meta/meta.dart';