Skip to content

Commit 779a321

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Ignore names _$foo when there is a missing .g.dart part.
Change-Id: I5a103cd362318b4db292b5f41da9e56a60f6431d Bug: #42832 Bug: #42977 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166820 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 4b531dc commit 779a321

File tree

8 files changed

+367
-51
lines changed

8 files changed

+367
-51
lines changed

pkg/analyzer/lib/src/context/source.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,30 @@ import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
1313
import 'package:analyzer/src/source/package_map_resolver.dart';
1414
import 'package:analyzer/src/workspace/package_build.dart';
1515

16+
/// Return `true` if the given [source] refers to a file that is assumed to be
17+
/// generated.
18+
bool isGeneratedSource(Source source) {
19+
if (source == null) {
20+
return false;
21+
}
22+
// TODO(brianwilkerson) Generalize this mechanism.
23+
const List<String> suffixes = <String>[
24+
'.g.dart',
25+
'.pb.dart',
26+
'.pbenum.dart',
27+
'.pbserver.dart',
28+
'.pbjson.dart',
29+
'.template.dart'
30+
];
31+
String fullName = source.fullName;
32+
for (String suffix in suffixes) {
33+
if (fullName.endsWith(suffix)) {
34+
return true;
35+
}
36+
}
37+
return false;
38+
}
39+
1640
/// Instances of the class `SourceFactory` resolve possibly relative URI's
1741
/// against an existing [Source].
1842
class SourceFactoryImpl implements SourceFactory {

pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:analyzer/dart/element/element.dart';
99
import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
1010
import 'package:analyzer/error/error.dart';
1111
import 'package:analyzer/error/listener.dart';
12+
import 'package:analyzer/src/context/source.dart';
1213
import 'package:analyzer/src/dart/analysis/file_state.dart';
1314
import 'package:analyzer/src/dart/analysis/testing_data.dart';
1415
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -829,7 +830,7 @@ class LibraryAnalyzer {
829830
}
830831
StringLiteral uriLiteral = directive.uri;
831832
CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
832-
if (_isGenerated(source)) {
833+
if (isGeneratedSource(source)) {
833834
errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
834835
}
835836
_getErrorReporter(file)
@@ -845,30 +846,6 @@ class LibraryAnalyzer {
845846
}
846847
}
847848
}
848-
849-
/// Return `true` if the given [source] refers to a file that is assumed to be
850-
/// generated.
851-
static bool _isGenerated(Source source) {
852-
if (source == null) {
853-
return false;
854-
}
855-
// TODO(brianwilkerson) Generalize this mechanism.
856-
const List<String> suffixes = <String>[
857-
'.g.dart',
858-
'.pb.dart',
859-
'.pbenum.dart',
860-
'.pbserver.dart',
861-
'.pbjson.dart',
862-
'.template.dart'
863-
];
864-
String fullName = source.fullName;
865-
for (String suffix in suffixes) {
866-
if (fullName.endsWith(suffix)) {
867-
return true;
868-
}
869-
}
870-
return false;
871-
}
872849
}
873850

874851
/// Analysis result for single file.

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,14 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl
14341434
@override
14351435
String get identifier => '${source.uri}';
14361436

1437+
@override
1438+
bool get isSynthetic {
1439+
if (linkedContext != null) {
1440+
return linkedContext.isSynthetic;
1441+
}
1442+
return super.isSynthetic;
1443+
}
1444+
14371445
@override
14381446
ElementKind get kind => ElementKind.COMPILATION_UNIT;
14391447

pkg/analyzer/lib/src/dart/element/scope.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/scope.dart';
7+
import 'package:analyzer/src/context/source.dart';
78
import 'package:analyzer/src/dart/element/element.dart';
89
import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
910
import 'package:meta/meta.dart';
@@ -148,6 +149,15 @@ class LibraryScope extends EnclosedScope {
148149
}
149150
}
150151
}
152+
153+
if (name.startsWith(r'_$')) {
154+
for (var partElement in _element.parts) {
155+
if (partElement.isSynthetic &&
156+
isGeneratedSource(partElement.source)) {
157+
return true;
158+
}
159+
}
160+
}
151161
}
152162

153163
return false;

pkg/analyzer/lib/src/dart/micro/library_analyzer.dart

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:analyzer/error/error.dart';
1010
import 'package:analyzer/error/listener.dart';
1111
import 'package:analyzer/file_system/file_system.dart';
1212
import 'package:analyzer/src/context/builder.dart';
13+
import 'package:analyzer/src/context/source.dart';
1314
import 'package:analyzer/src/dart/ast/ast.dart';
1415
import 'package:analyzer/src/dart/ast/utilities.dart';
1516
import 'package:analyzer/src/dart/constant/compute.dart';
@@ -789,7 +790,7 @@ class LibraryAnalyzer {
789790
}
790791
StringLiteral uriLiteral = directive.uri;
791792
CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
792-
if (_isGenerated(source)) {
793+
if (isGeneratedSource(source)) {
793794
errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
794795
}
795796
_getErrorReporter(file)
@@ -805,30 +806,6 @@ class LibraryAnalyzer {
805806
}
806807
}
807808
}
808-
809-
/// Return `true` if the given [source] refers to a file that is assumed to be
810-
/// generated.
811-
static bool _isGenerated(Source source) {
812-
if (source == null) {
813-
return false;
814-
}
815-
// TODO(brianwilkerson) Generalize this mechanism.
816-
const List<String> suffixes = <String>[
817-
'.g.dart',
818-
'.pb.dart',
819-
'.pbenum.dart',
820-
'.pbserver.dart',
821-
'.pbjson.dart',
822-
'.template.dart'
823-
];
824-
String fullName = source.fullName;
825-
for (String suffix in suffixes) {
826-
if (fullName.endsWith(suffix)) {
827-
return true;
828-
}
829-
}
830-
return false;
831-
}
832809
}
833810

834811
/// Analysis result for single file.

pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,113 @@ main() {
1515
}
1616

1717
@reflectiveTest
18-
class ExtendsNonClassTest extends PubPackageResolutionTest {}
18+
class ExtendsNonClassTest extends PubPackageResolutionTest {
19+
test_undefined() async {
20+
await assertErrorsInCode(r'''
21+
class C extends A {}
22+
''', [
23+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 1),
24+
]);
25+
}
26+
27+
test_undefined_ignore_import_prefix() async {
28+
await assertErrorsInCode(r'''
29+
import 'a.dart' as p;
30+
31+
class C extends p.A {}
32+
''', [
33+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
34+
]);
35+
}
36+
37+
test_undefined_ignore_import_show_it() async {
38+
await assertErrorsInCode(r'''
39+
import 'a.dart' show A;
40+
41+
class C extends A {}
42+
''', [
43+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
44+
]);
45+
}
46+
47+
test_undefined_ignore_import_show_other() async {
48+
await assertErrorsInCode(r'''
49+
import 'a.dart' show B;
50+
51+
class C extends A {}
52+
''', [
53+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
54+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 41, 1),
55+
]);
56+
}
57+
58+
test_undefined_ignore_part_exists_uriGenerated_nameIgnorable() async {
59+
newFile('$testPackageLibPath/a.g.dart', content: r'''
60+
part of 'test.dart';
61+
''');
62+
63+
await assertErrorsInCode(r'''
64+
part 'a.g.dart';
65+
66+
class C extends _$A {}
67+
''', [
68+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 34, 3),
69+
]);
70+
}
71+
72+
test_undefined_ignore_part_notExist_uriGenerated_nameIgnorable() async {
73+
await assertErrorsInCode(r'''
74+
part 'a.g.dart';
75+
76+
class C extends _$A {}
77+
''', [
78+
error(CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED, 5, 10),
79+
]);
80+
}
81+
82+
test_undefined_ignore_part_notExist_uriGenerated_nameNotIgnorable() async {
83+
await assertErrorsInCode(r'''
84+
part 'a.g.dart';
85+
86+
class C extends A {}
87+
''', [
88+
error(CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED, 5, 10),
89+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 34, 1),
90+
]);
91+
}
92+
93+
test_undefined_ignore_part_notExist_uriNotGenerated_nameIgnorable() async {
94+
await assertErrorsInCode(r'''
95+
part 'a.dart';
96+
97+
class C extends _$A {}
98+
''', [
99+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 8),
100+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 32, 3),
101+
]);
102+
}
103+
104+
test_undefined_ignore_part_notExist_uriNotGenerated_nameNotIgnorable() async {
105+
await assertErrorsInCode(r'''
106+
part 'a.dart';
107+
108+
class C extends A {}
109+
''', [
110+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 8),
111+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 32, 1),
112+
]);
113+
}
114+
115+
test_undefined_import_exists_prefixed() async {
116+
await assertErrorsInCode(r'''
117+
import 'dart:math' as p;
118+
119+
class C extends p.A {}
120+
''', [
121+
error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 42, 3),
122+
]);
123+
}
124+
}
19125

20126
@reflectiveTest
21127
class ExtendsNonClassWithNullSafetyTest extends ExtendsNonClassTest

pkg/analyzer/test/src/diagnostics/mixin_of_non_class_test.dart

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,112 @@ class C = A with B;
5555
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 39, 1),
5656
]);
5757
}
58+
59+
test_undefined() async {
60+
await assertErrorsInCode(r'''
61+
class C with M {}
62+
''', [
63+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 13, 1),
64+
]);
65+
}
66+
67+
test_undefined_ignore_import_prefix() async {
68+
await assertErrorsInCode(r'''
69+
import 'a.dart' as p;
70+
71+
class C with p.M {}
72+
''', [
73+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
74+
]);
75+
}
76+
77+
test_undefined_ignore_import_show_it() async {
78+
await assertErrorsInCode(r'''
79+
import 'a.dart' show M;
80+
81+
class C with M {}
82+
''', [
83+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
84+
]);
85+
}
86+
87+
test_undefined_ignore_import_show_other() async {
88+
await assertErrorsInCode(r'''
89+
import 'a.dart' show N;
90+
91+
class C with M {}
92+
''', [
93+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 8),
94+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 38, 1),
95+
]);
96+
}
97+
98+
test_undefined_ignore_part_exists_uriGenerated_nameIgnorable() async {
99+
newFile('$testPackageLibPath/a.g.dart', content: r'''
100+
part of 'test.dart';
101+
''');
102+
103+
await assertErrorsInCode(r'''
104+
part 'a.g.dart';
105+
106+
class C with _$M {}
107+
''', [
108+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 31, 3),
109+
]);
110+
}
111+
112+
test_undefined_ignore_part_notExist_uriGenerated_nameIgnorable() async {
113+
await assertErrorsInCode(r'''
114+
part 'a.g.dart';
115+
116+
class C with _$M {}
117+
''', [
118+
error(CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED, 5, 10),
119+
]);
120+
}
121+
122+
test_undefined_ignore_part_notExist_uriGenerated_nameNotIgnorable() async {
123+
await assertErrorsInCode(r'''
124+
part 'a.g.dart';
125+
126+
class C with M {}
127+
''', [
128+
error(CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED, 5, 10),
129+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 31, 1),
130+
]);
131+
}
132+
133+
test_undefined_ignore_part_notExist_uriNotGenerated_nameIgnorable() async {
134+
await assertErrorsInCode(r'''
135+
part 'a.dart';
136+
137+
class C with _$M {}
138+
''', [
139+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 8),
140+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 29, 3),
141+
]);
142+
}
143+
144+
test_undefined_ignore_part_notExist_uriNotGenerated_nameNotIgnorable() async {
145+
await assertErrorsInCode(r'''
146+
part 'a.dart';
147+
148+
class C with M {}
149+
''', [
150+
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 8),
151+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 29, 1),
152+
]);
153+
}
154+
155+
test_undefined_import_exists_prefixed() async {
156+
await assertErrorsInCode(r'''
157+
import 'dart:math' as p;
158+
159+
class C with p.M {}
160+
''', [
161+
error(CompileTimeErrorCode.MIXIN_OF_NON_CLASS, 39, 3),
162+
]);
163+
}
58164
}
59165

60166
@reflectiveTest

0 commit comments

Comments
 (0)