Skip to content

Commit a0227f5

Browse files
committed
Issue 44063. Report IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE hint.
Bug: #44063 Change-Id: I69c6f84da9a9c928e177507cedb30e06a561f3f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170441 Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 786ab13 commit a0227f5

29 files changed

+292
-109
lines changed

pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class AnalysisDomainGetErrorsTest
2828
Directory(path.join(sdkPath, 'lib', 'async')).createSync(recursive: true);
2929
Directory(path.join(sdkPath, 'lib', 'fake')).createSync(recursive: true);
3030

31-
File(path.join(sdkPath, 'version')).writeAsStringSync('2.10.0');
31+
File(path.join(sdkPath, 'version')).writeAsStringSync('2.12.0');
3232

3333
File(path.join(sdkPath, 'lib', 'core', 'core.dart')).writeAsStringSync(r'''
3434
library dart.core;

pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analysis_server/src/services/correction/fix.dart';
6+
import 'package:analyzer/src/error/codes.dart';
67
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
78
import 'package:test_reflective_loader/test_reflective_loader.dart';
89

@@ -517,7 +518,9 @@ main() {
517518
A a = new A(callback: (int a) { });
518519
print(a);
519520
}
520-
''');
521+
''',
522+
errorFilter: (error) =>
523+
error.errorCode == HintCode.MISSING_REQUIRED_PARAM);
521524
}
522525

523526
Future<void> test_constructor_single_closure_nnbd_into_legacy() async {

pkg/analyzer/lib/error/error.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ const List<ErrorCode> errorCodeValues = [
489489
HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE,
490490
HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE,
491491
HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION,
492+
HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE,
492493
HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL,
493494
HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE,
494495
HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,

pkg/analyzer/lib/src/dart/error/hint_codes.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,16 @@ class HintCode extends AnalyzerErrorCode {
571571
correction: "Try changing the import to not be deferred, or "
572572
"rename the function in the imported library.");
573573

574+
/**
575+
* https://github.com/dart-lang/sdk/issues/44063
576+
*/
577+
static const HintCode IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE = HintCode(
578+
'IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE',
579+
"The library '{0}' is legacy, and should not be imported into "
580+
"a null safe library.",
581+
correction: "Try migrating the imported library.",
582+
);
583+
574584
/**
575585
* When "strict-inference" is enabled, collection literal types must be
576586
* inferred via the context type, or have type arguments.

pkg/analyzer/lib/src/error/best_practices_verifier.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
504504
_checkForLoadLibraryFunction(node, importElement);
505505
}
506506
_invalidAccessVerifier.verifyImport(node);
507+
_checkForImportOfLegacyLibraryIntoNullSafe(node);
507508
super.visitImportDirective(node);
508509
}
509510

@@ -922,6 +923,24 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
922923
}
923924
}
924925

926+
void _checkForImportOfLegacyLibraryIntoNullSafe(ImportDirective node) {
927+
if (!_isNonNullableByDefault) {
928+
return;
929+
}
930+
931+
var importElement = node.element as ImportElement;
932+
var importedLibrary = importElement.importedLibrary;
933+
if (importedLibrary == null || importedLibrary.isNonNullableByDefault) {
934+
return;
935+
}
936+
937+
_errorReporter.reportErrorForNode(
938+
HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE,
939+
node.uri,
940+
[importedLibrary.source.uri],
941+
);
942+
}
943+
925944
/// Check that the namespace exported by [node] does not include any elements
926945
/// annotated with `@internal`.
927946
void _checkForInternalExport(ExportDirective node) {

pkg/analyzer/test/src/dart/analysis/base.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class BaseAnalysisDriverTest with ResourceProviderMixin {
6363
final List<ExceptionResult> allExceptions = <ExceptionResult>[];
6464

6565
String testProject;
66+
String testProject2;
6667
String testFile;
6768
String testCode;
6869

@@ -81,7 +82,7 @@ class BaseAnalysisDriverTest with ResourceProviderMixin {
8182
{Map<String, List<Folder>> packageMap,
8283
SummaryDataStore externalSummaries}) {
8384
packageMap ??= <String, List<Folder>>{
84-
'test': [getFolder(testProject)],
85+
'test': [getFolder('$testProject/lib')],
8586
'aaa': [getFolder('/aaa/lib')],
8687
'bbb': [getFolder('/bbb/lib')],
8788
};
@@ -161,7 +162,8 @@ class BaseAnalysisDriverTest with ResourceProviderMixin {
161162

162163
void setUp() {
163164
sdk = MockSdk(resourceProvider: resourceProvider);
164-
testProject = convertPath('/test/lib');
165+
testProject = convertPath('/test');
166+
testProject2 = convertPath('/test/lib');
165167
testFile = convertPath('/test/lib/test.dart');
166168
logger = PerformanceLog(logBuffer);
167169
scheduler = AnalysisDriverScheduler(logger);

pkg/analyzer/test/src/dart/analysis/index_test.dart

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ mixin M5 on M2 {}
136136
}
137137

138138
test_isExtendedBy_ClassDeclaration_isQualified() async {
139-
newFile('$testProject/lib.dart', content: '''
139+
newFile('$testProject2/lib.dart', content: '''
140140
class A {}
141141
''');
142142
await _indexTestUnit('''
@@ -169,7 +169,7 @@ class C = A with B;
169169
}
170170

171171
test_isExtendedBy_ClassTypeAlias_isQualified() async {
172-
newFile('$testProject/lib.dart', content: '''
172+
newFile('$testProject2/lib.dart', content: '''
173173
class A {}
174174
''');
175175
await _indexTestUnit('''
@@ -195,7 +195,7 @@ class B implements A {} // 2
195195
}
196196

197197
test_isImplementedBy_ClassDeclaration_isQualified() async {
198-
newFile('$testProject/lib.dart', content: '''
198+
newFile('$testProject2/lib.dart', content: '''
199199
class A {}
200200
''');
201201
await _indexTestUnit('''
@@ -243,7 +243,7 @@ mixin M on A {} // 2
243243
}
244244

245245
test_isInvokedBy_FunctionElement() async {
246-
newFile('$testProject/lib.dart', content: '''
246+
newFile('$testProject2/lib.dart', content: '''
247247
library lib;
248248
foo() {}
249249
''');
@@ -419,7 +419,7 @@ class B extends Object with A {} // 2
419419
}
420420

421421
test_isMixedInBy_ClassDeclaration_isQualified() async {
422-
newFile('$testProject/lib.dart', content: '''
422+
newFile('$testProject2/lib.dart', content: '''
423423
class A {}
424424
''');
425425
await _indexTestUnit('''
@@ -547,7 +547,7 @@ main() {
547547
}
548548

549549
test_isReferencedBy_ClassElement_invocation_isQualified() async {
550-
newFile('$testProject/lib.dart', content: '''
550+
newFile('$testProject2/lib.dart', content: '''
551551
class A {}
552552
''');
553553
await _indexTestUnit('''
@@ -586,7 +586,7 @@ main(B p) {
586586
}
587587

588588
test_isReferencedBy_CompilationUnitElement_export() async {
589-
newFile('$testProject/lib.dart', content: '''
589+
newFile('$testProject2/lib.dart', content: '''
590590
library lib;
591591
''');
592592
await _indexTestUnit('''
@@ -597,7 +597,7 @@ export 'lib.dart';
597597
}
598598

599599
test_isReferencedBy_CompilationUnitElement_import() async {
600-
newFile('$testProject/lib.dart', content: '''
600+
newFile('$testProject2/lib.dart', content: '''
601601
library lib;
602602
''');
603603
await _indexTestUnit('''
@@ -608,7 +608,7 @@ import 'lib.dart';
608608
}
609609

610610
test_isReferencedBy_CompilationUnitElement_part() async {
611-
newFile('$testProject/my_unit.dart', content: 'part of my_lib;');
611+
newFile('$testProject2/my_unit.dart', content: 'part of my_lib;');
612612
await _indexTestUnit('''
613613
library my_lib;
614614
part 'my_unit.dart';
@@ -618,8 +618,8 @@ part 'my_unit.dart';
618618
}
619619

620620
test_isReferencedBy_CompilationUnitElement_part_inPart() async {
621-
newFile('$testProject/a.dart', content: 'part of lib;');
622-
newFile('$testProject/b.dart', content: '''
621+
newFile('$testProject2/a.dart', content: 'part of lib;');
622+
newFile('$testProject2/b.dart', content: '''
623623
library lib;
624624
part 'a.dart';
625625
''');
@@ -899,7 +899,7 @@ main() {
899899
}
900900

901901
test_isReferencedBy_FunctionElement_with_LibraryElement() async {
902-
newFile('$testProject/foo.dart', content: r'''
902+
newFile('$testProject2/foo.dart', content: r'''
903903
bar() {}
904904
''');
905905
await _indexTestUnit('''
@@ -957,8 +957,8 @@ class A {
957957
}
958958

959959
test_isReferencedBy_MultiplyDefinedElement() async {
960-
newFile('$testProject/a1.dart', content: 'class A {}');
961-
newFile('$testProject/a2.dart', content: 'class A {}');
960+
newFile('$testProject2/a1.dart', content: 'class A {}');
961+
newFile('$testProject2/a2.dart', content: 'class A {}');
962962
await _indexTestUnit('''
963963
import 'a1.dart';
964964
import 'a2.dart';
@@ -1153,7 +1153,7 @@ main(bool b) {
11531153
}
11541154

11551155
test_isReferencedBy_TopLevelVariableElement() async {
1156-
newFile('$testProject/lib.dart', content: '''
1156+
newFile('$testProject2/lib.dart', content: '''
11571157
library lib;
11581158
var V;
11591159
''');
@@ -1177,7 +1177,7 @@ main() {
11771177
}
11781178

11791179
test_isReferencedBy_TopLevelVariableElement_synthetic_hasGetterSetter() async {
1180-
newFile('$testProject/lib.dart', content: '''
1180+
newFile('$testProject2/lib.dart', content: '''
11811181
int get V => 0;
11821182
void set V(_) {}
11831183
''');
@@ -1189,7 +1189,7 @@ import 'lib.dart' show V;
11891189
}
11901190

11911191
test_isReferencedBy_TopLevelVariableElement_synthetic_hasSetter() async {
1192-
newFile('$testProject/lib.dart', content: '''
1192+
newFile('$testProject2/lib.dart', content: '''
11931193
void set V(_) {}
11941194
''');
11951195
await _indexTestUnit('''
@@ -1224,7 +1224,7 @@ class A {
12241224

12251225
test_subtypes_classDeclaration() async {
12261226
String libP = 'package:test/lib.dart;package:test/lib.dart';
1227-
newFile('$testProject/lib.dart', content: '''
1227+
newFile('$testProject2/lib.dart', content: '''
12281228
class A {}
12291229
class B {}
12301230
class C {}
@@ -1274,7 +1274,7 @@ class Z implements E, D {
12741274

12751275
test_subtypes_classTypeAlias() async {
12761276
String libP = 'package:test/lib.dart;package:test/lib.dart';
1277-
newFile('$testProject/lib.dart', content: '''
1277+
newFile('$testProject2/lib.dart', content: '''
12781278
class A {}
12791279
class B {}
12801280
class C {}
@@ -1312,7 +1312,7 @@ class X extends dynamic {
13121312

13131313
test_subtypes_mixinDeclaration() async {
13141314
String libP = 'package:test/lib.dart;package:test/lib.dart';
1315-
newFile('$testProject/lib.dart', content: '''
1315+
newFile('$testProject2/lib.dart', content: '''
13161316
class A {}
13171317
class B {}
13181318
class C {}

pkg/analyzer/test/src/dart/analysis/search_test.dart

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ List<A> v2 = null;
261261
}
262262

263263
test_searchReferences_ClassElement_definedOutside() async {
264-
newFile('$testProject/lib.dart', content: r'''
264+
newFile('$testProject2/lib.dart', content: r'''
265265
class A {};
266266
''');
267267
await _resolveTestUnit('''
@@ -317,7 +317,7 @@ class B extends Object with A {} // with
317317
}
318318

319319
test_searchReferences_CompilationUnitElement() async {
320-
newFile('$testProject/foo.dart');
320+
newFile('$testProject2/foo.dart');
321321
await _resolveTestUnit('''
322322
import 'foo.dart'; // import
323323
export 'foo.dart'; // export
@@ -354,7 +354,7 @@ main() {
354354
}
355355

356356
test_searchReferences_ConstructorElement_default_otherFile() async {
357-
String other = convertPath('$testProject/other.dart');
357+
String other = convertPath('$testProject2/other.dart');
358358
String otherCode = '''
359359
import 'test.dart';
360360
main() {
@@ -686,8 +686,8 @@ label:
686686
test_searchReferences_LibraryElement() async {
687687
var codeA = 'part of lib; // A';
688688
var codeB = 'part of lib; // B';
689-
newFile('$testProject/unitA.dart', content: codeA);
690-
newFile('$testProject/unitB.dart', content: codeB);
689+
newFile('$testProject2/unitA.dart', content: codeA);
690+
newFile('$testProject2/unitB.dart', content: codeB);
691691
await _resolveTestUnit('''
692692
library lib;
693693
part 'unitA.dart';
@@ -1103,7 +1103,7 @@ main() {
11031103
part of my_lib;
11041104
ppp.Future c;
11051105
''';
1106-
newFile('$testProject/my_part.dart', content: partCode);
1106+
newFile('$testProject2/my_part.dart', content: partCode);
11071107
await _resolveTestUnit('''
11081108
library my_lib;
11091109
import 'dart:async' as ppp;
@@ -1156,9 +1156,9 @@ main() {
11561156
}
11571157

11581158
test_searchReferences_private_declaredInDefiningUnit() async {
1159-
String p1 = convertPath('$testProject/part1.dart');
1160-
String p2 = convertPath('$testProject/part2.dart');
1161-
String p3 = convertPath('$testProject/part3.dart');
1159+
String p1 = convertPath('$testProject2/part1.dart');
1160+
String p2 = convertPath('$testProject2/part2.dart');
1161+
String p3 = convertPath('$testProject2/part3.dart');
11621162
String code1 = 'part of lib; _C v1;';
11631163
String code2 = 'part of lib; _C v2;';
11641164
newFile(p1, content: code1);
@@ -1192,9 +1192,9 @@ _C v;
11921192
}
11931193

11941194
test_searchReferences_private_declaredInPart() async {
1195-
String p = convertPath('$testProject/lib.dart');
1196-
String p1 = convertPath('$testProject/part1.dart');
1197-
String p2 = convertPath('$testProject/part2.dart');
1195+
String p = convertPath('$testProject2/lib.dart');
1196+
String p1 = convertPath('$testProject2/part1.dart');
1197+
String p2 = convertPath('$testProject2/part2.dart');
11981198

11991199
var code = '''
12001200
library lib;
@@ -1369,7 +1369,7 @@ class A {
13691369
}
13701370

13711371
test_searchReferences_TopLevelVariableElement() async {
1372-
newFile('$testProject/lib.dart', content: '''
1372+
newFile('$testProject2/lib.dart', content: '''
13731373
library lib;
13741374
var V;
13751375
''');
@@ -1654,8 +1654,8 @@ class A {
16541654
}
16551655

16561656
test_subtypes_files() async {
1657-
String pathB = convertPath('$testProject/b.dart');
1658-
String pathC = convertPath('$testProject/c.dart');
1657+
String pathB = convertPath('$testProject2/b.dart');
1658+
String pathC = convertPath('$testProject2/c.dart');
16591659
newFile(pathB, content: r'''
16601660
import 'test.dart';
16611661
class B extends A {}

pkg/analyzer/test/src/dart/resolution/constant_test.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,15 @@ const cInt = const int.fromEnvironment('foo', defaultValue: 1);
347347
const cString = const String.fromEnvironment('foo', defaultValue: 'bar');
348348
''');
349349

350-
await assertNoErrorsInCode(r'''
350+
await assertErrorsInCode(r'''
351351
import 'a.dart';
352352
353353
const vBool = cBool;
354354
const vInt = cInt;
355355
const vString = cString;
356-
''');
356+
''', [
357+
error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
358+
]);
357359

358360
DartObjectImpl evaluate(String name) {
359361
return findElement.topVar(name).computeConstantValue();

0 commit comments

Comments
 (0)