Skip to content

Commit 3962edc

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Convert opt-in elements to legacy when resolving annotations.
Change-Id: Ifc32ec66e9e45dcaa206c662785bb7d4c054b701 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133166 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
1 parent d44c74c commit 3962edc

File tree

3 files changed

+253
-0
lines changed

3 files changed

+253
-0
lines changed

pkg/analyzer/lib/src/generated/element_resolver.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
10941094
if (element1 is ClassElement) {
10951095
constructor = _instantiateAnnotationClass(element1)
10961096
.lookUpConstructor(null, _definingLibrary);
1097+
constructor = _resolver.toLegacyElement(constructor);
10971098
} else if (element1 == null) {
10981099
undefined = true;
10991100
}
@@ -1107,6 +1108,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
11071108
// Class.CONST - not resolved yet
11081109
if (element1 is ClassElement) {
11091110
element2 = element1.lookUpGetter(nameNode2.name, _definingLibrary);
1111+
element2 = _resolver.toLegacyElement(element2);
11101112
}
11111113
// prefix.CONST or Class.CONST
11121114
if (element2 is PropertyAccessorElement) {
@@ -1118,11 +1120,13 @@ class ElementResolver extends SimpleAstVisitor<void> {
11181120
// prefix.Class()
11191121
if (element2 is ClassElement) {
11201122
constructor = element2.unnamedConstructor;
1123+
constructor = _resolver.toLegacyElement(constructor);
11211124
}
11221125
// Class.constructor(args)
11231126
if (element1 is ClassElement) {
11241127
constructor = _instantiateAnnotationClass(element1)
11251128
.lookUpConstructor(nameNode2.name, _definingLibrary);
1129+
constructor = _resolver.toLegacyElement(constructor);
11261130
nameNode2.staticElement = constructor;
11271131
}
11281132
if (element1 == null && element2 == null) {
@@ -1141,6 +1145,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
11411145
PropertyAccessorElement getter =
11421146
element2.lookUpGetter(name3, _definingLibrary);
11431147
if (getter != null) {
1148+
getter = _resolver.toLegacyElement(getter);
11441149
nameNode3.staticElement = getter;
11451150
annotation.element = getter;
11461151
_resolveAnnotationElementGetter(annotation, getter);
@@ -1149,6 +1154,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
11491154
// prefix.Class.constructor(args)
11501155
constructor = _instantiateAnnotationClass(element2)
11511156
.lookUpConstructor(name3, _definingLibrary);
1157+
constructor = _resolver.toLegacyElement(constructor);
11521158
nameNode3.staticElement = constructor;
11531159
} else if (element2 == null) {
11541160
undefined = true;

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

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/dart/analysis/features.dart';
56
import 'package:analyzer/dart/ast/ast.dart';
7+
import 'package:analyzer/src/generated/engine.dart';
8+
import 'package:analyzer/src/test_utilities/find_element.dart';
69
import 'package:test/test.dart';
710
import 'package:test_reflective_loader/test_reflective_loader.dart';
811

@@ -12,6 +15,7 @@ import 'driver_resolution.dart';
1215
main() {
1316
defineReflectiveSuite(() {
1417
defineReflectiveTests(MetadataResolutionTest);
18+
defineReflectiveTests(MetadataResolutionWithNnbdTest);
1519
});
1620
}
1721

@@ -174,3 +178,220 @@ class B {}
174178
return buffer.toString();
175179
}
176180
}
181+
182+
@reflectiveTest
183+
class MetadataResolutionWithNnbdTest extends DriverResolutionTest {
184+
@override
185+
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
186+
..contextFeatures = FeatureSet.forTesting(
187+
sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
188+
189+
ImportFindElement get import_a {
190+
return findElement.importFind('package:test/a.dart');
191+
}
192+
193+
@override
194+
bool get typeToStringWithNullability => true;
195+
196+
test_optIn_fromOptOut_class() async {
197+
newFile('/test/lib/a.dart', content: r'''
198+
class A {
199+
const A(int a);
200+
}
201+
''');
202+
203+
await assertNoErrorsInCode(r'''
204+
// @dart = 2.7
205+
import 'a.dart';
206+
207+
@A(0)
208+
void f() {}
209+
''');
210+
211+
assertElement2(
212+
findNode.simple('A('),
213+
declaration: import_a.class_('A'),
214+
);
215+
216+
assertElement2(
217+
findNode.annotation('@A'),
218+
declaration: import_a.unnamedConstructor('A'),
219+
isLegacy: true,
220+
);
221+
}
222+
223+
test_optIn_fromOptOut_class_constructor() async {
224+
newFile('/test/lib/a.dart', content: r'''
225+
class A {
226+
const A.named(int a);
227+
}
228+
''');
229+
230+
await assertNoErrorsInCode(r'''
231+
// @dart = 2.7
232+
import 'a.dart';
233+
234+
@A.named(0)
235+
void f() {}
236+
''');
237+
238+
assertElement2(
239+
findNode.simple('A.named('),
240+
declaration: import_a.class_('A'),
241+
);
242+
243+
assertElement2(
244+
findNode.annotation('@A'),
245+
declaration: import_a.constructor('named', of: 'A'),
246+
isLegacy: true,
247+
);
248+
}
249+
250+
test_optIn_fromOptOut_class_getter() async {
251+
newFile('/test/lib/a.dart', content: r'''
252+
class A {
253+
const foo = 0;
254+
}
255+
''');
256+
257+
await assertNoErrorsInCode(r'''
258+
// @dart = 2.7
259+
import 'a.dart';
260+
261+
@A.foo
262+
void f() {}
263+
''');
264+
265+
assertElement2(
266+
findNode.simple('A.foo'),
267+
declaration: import_a.class_('A'),
268+
);
269+
270+
assertElement2(
271+
findNode.annotation('@A.foo'),
272+
declaration: import_a.getter('foo'),
273+
isLegacy: true,
274+
);
275+
}
276+
277+
test_optIn_fromOptOut_getter() async {
278+
newFile('/test/lib/a.dart', content: r'''
279+
const foo = 0;
280+
''');
281+
282+
await assertNoErrorsInCode(r'''
283+
// @dart = 2.7
284+
import 'a.dart';
285+
286+
@foo
287+
void f() {}
288+
''');
289+
290+
assertElement2(
291+
findNode.annotation('@foo'),
292+
declaration: import_a.topGet('foo'),
293+
isLegacy: true,
294+
);
295+
}
296+
297+
test_optIn_fromOptOut_prefix_class() async {
298+
newFile('/test/lib/a.dart', content: r'''
299+
class A {
300+
const A(int a);
301+
}
302+
''');
303+
304+
await assertNoErrorsInCode(r'''
305+
// @dart = 2.7
306+
import 'a.dart' as a;
307+
308+
@a.A(0)
309+
void f() {}
310+
''');
311+
312+
assertElement2(
313+
findNode.simple('A('),
314+
declaration: import_a.class_('A'),
315+
);
316+
317+
assertElement2(
318+
findNode.annotation('@a.A'),
319+
declaration: import_a.unnamedConstructor('A'),
320+
isLegacy: true,
321+
);
322+
}
323+
324+
test_optIn_fromOptOut_prefix_class_constructor() async {
325+
newFile('/test/lib/a.dart', content: r'''
326+
class A {
327+
const A.named(int a);
328+
}
329+
''');
330+
331+
await assertNoErrorsInCode(r'''
332+
// @dart = 2.7
333+
import 'a.dart' as a;
334+
335+
@a.A.named(0)
336+
void f() {}
337+
''');
338+
339+
assertElement2(
340+
findNode.simple('A.named('),
341+
declaration: import_a.class_('A'),
342+
);
343+
344+
assertElement2(
345+
findNode.annotation('@a.A'),
346+
declaration: import_a.constructor('named', of: 'A'),
347+
isLegacy: true,
348+
);
349+
}
350+
351+
test_optIn_fromOptOut_prefix_class_getter() async {
352+
newFile('/test/lib/a.dart', content: r'''
353+
class A {
354+
const foo = 0;
355+
}
356+
''');
357+
358+
await assertNoErrorsInCode(r'''
359+
// @dart = 2.7
360+
import 'a.dart' as a;
361+
362+
@a.A.foo
363+
void f() {}
364+
''');
365+
366+
assertElement2(
367+
findNode.simple('A.foo'),
368+
declaration: import_a.class_('A'),
369+
);
370+
371+
assertElement2(
372+
findNode.annotation('@a.A'),
373+
declaration: import_a.getter('foo'),
374+
isLegacy: true,
375+
);
376+
}
377+
378+
test_optIn_fromOptOut_prefix_getter() async {
379+
newFile('/test/lib/a.dart', content: r'''
380+
const foo = 0;
381+
''');
382+
383+
await assertNoErrorsInCode(r'''
384+
// @dart = 2.7
385+
import 'a.dart' as a;
386+
387+
@a.foo
388+
void f() {}
389+
''');
390+
391+
assertElement2(
392+
findNode.annotation('@a.foo'),
393+
declaration: import_a.topGet('foo'),
394+
isLegacy: true,
395+
);
396+
}
397+
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,32 @@ mixin ResolutionTest implements ResourceProviderMixin {
143143
expect(actual, same(expected));
144144
}
145145

146+
void assertElement2(
147+
Object nodeOrElement, {
148+
@required Element declaration,
149+
bool isLegacy = false,
150+
Map<String, String> substitution = const {},
151+
}) {
152+
Element element;
153+
if (nodeOrElement is AstNode) {
154+
element = getNodeElement(nodeOrElement);
155+
} else {
156+
element = nodeOrElement as Element;
157+
}
158+
159+
var actualDeclaration = element?.declaration;
160+
expect(actualDeclaration, same(declaration));
161+
162+
if (element is Member) {
163+
expect(element.isLegacy, isLegacy);
164+
assertSubstitution(element.substitution, substitution);
165+
} else {
166+
if (isLegacy || substitution.isNotEmpty) {
167+
fail('Expected to be a Member: (${element.runtimeType}) $element');
168+
}
169+
}
170+
}
171+
146172
void assertElementLibraryUri(Element element, String expected) {
147173
var uri = element.library.source.uri;
148174
expect('$uri', expected);

0 commit comments

Comments
 (0)