Temporary support for declaration macros to declare top-level variables.

For now we put them into the defining unit, eventually they will
stay in the augmentation library.

Change-Id: I1fc5800f9c54248e24df68cc6f4ee7acf8f8e386
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243648
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-05-04 21:08:54 +00:00 committed by Commit Bot
parent 84ca405b35
commit a0da1a1dee
7 changed files with 91 additions and 52 deletions

View file

@ -84,7 +84,7 @@ import 'package:meta/meta.dart';
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 217;
static const int DATA_VERSION = 218;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.

View file

@ -3709,7 +3709,7 @@ class LibraryElementImpl extends _ExistingElementImpl
List<ExtensionElement> get accessibleExtensions => scope.extensions;
@override
CompilationUnitElement get definingCompilationUnit =>
CompilationUnitElementImpl get definingCompilationUnit =>
_definingCompilationUnit;
/// Set the compilation unit that defines this library to the given

View file

@ -312,6 +312,7 @@ class TopLevelVariableElementFlags {
static const int _isExternal = 1 << 2;
static const int _isFinal = 1 << 3;
static const int _isLate = 1 << 4;
static const int _isTempAugmentation = 1 << 5;
static void read(
SummaryDataReader reader,
@ -323,6 +324,7 @@ class TopLevelVariableElementFlags {
element.isExternal = (byte & _isExternal) != 0;
element.isFinal = (byte & _isFinal) != 0;
element.isLate = (byte & _isLate) != 0;
element.isTempAugmentation = (byte & _isTempAugmentation) != 0;
}
static void write(BufferedSink sink, TopLevelVariableElementImpl element) {
@ -332,6 +334,7 @@ class TopLevelVariableElementFlags {
result |= element.isExternal ? _isExternal : 0;
result |= element.isFinal ? _isFinal : 0;
result |= element.isLate ? _isLate : 0;
result |= element.isTempAugmentation ? _isTempAugmentation : 0;
sink.writeByte(result);
}
}

View file

@ -238,6 +238,7 @@ class LibraryBuilder {
TypesBuilder(linker).build(nodesToBuildType);
// Transplant built elements as if the augmentation was applied.
final augmentedUnitElement = element.definingCompilationUnit;
for (final augmentation in unitElement.classes) {
// TODO(scheglov) if augmentation
final augmented = element.getType(augmentation.name);
@ -260,6 +261,14 @@ class LibraryBuilder {
];
}
}
augmentedUnitElement.accessors = [
...augmentedUnitElement.accessors,
...unitElement.accessors,
];
augmentedUnitElement.topLevelVariables = [
...augmentedUnitElement.topLevelVariables,
...unitElement.topLevelVariables,
];
}
Future<void> executeMacroTypesPhase() async {

View file

@ -177,8 +177,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
String methodName = "m";
MethodElement method = ElementFactory.methodElement(methodName, intNone);
classA.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpConcreteMethod(methodName, library), same(method));
}
@ -193,8 +192,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ElementFactory.methodElement(methodName, intNone);
method.isAbstract = true;
classA.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpConcreteMethod(methodName, library), isNull);
}
@ -217,8 +215,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ElementFactory.methodElement(methodName, intNone);
method.isAbstract = true;
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpConcreteMethod(methodName, library),
same(inheritedMethod));
}
@ -240,8 +237,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, intNone);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpConcreteMethod(methodName, library), same(method));
}
@ -264,8 +260,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, intNone);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpConcreteMethod(methodName, library), same(method));
}
@ -283,8 +278,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpConcreteMethod(methodName, library),
same(inheritedMethod));
}
@ -294,8 +288,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
// }
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpConcreteMethod("m", library), isNull);
}
@ -309,8 +302,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, intNone);
classA.accessors = <PropertyAccessorElement>[getter];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpGetter(getterName, library), same(getter));
}
@ -328,8 +320,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
classA.accessors = <PropertyAccessorElement>[getter];
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpGetter(getterName, library), same(getter));
}
@ -338,8 +329,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
// }
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpGetter("g", library), isNull);
}
@ -353,8 +343,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classA.lookUpGetter("g", library), isNull);
}
@ -364,8 +353,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
String methodName = "m";
MethodElement method = ElementFactory.methodElement(methodName, intNone);
classA.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpMethod(methodName, library), same(method));
}
@ -377,16 +365,14 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
classA.methods = <MethodElement>[method];
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpMethod(methodName, library), same(method));
}
void test_lookUpMethod_undeclared() {
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpMethod("m", library), isNull);
}
@ -396,8 +382,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classA.lookUpMethod("m", library), isNull);
}
@ -411,8 +396,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
PropertyAccessorElement setter =
ElementFactory.setterElement(setterName, false, intNone);
classA.accessors = <PropertyAccessorElement>[setter];
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpSetter(setterName, library), same(setter));
}
@ -430,8 +414,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
classA.accessors = <PropertyAccessorElement>[setter];
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classB.lookUpSetter(setterName, library), same(setter));
}
@ -440,8 +423,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
// }
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA];
(library.definingCompilationUnit).classes = <ClassElement>[classA];
expect(classA.lookUpSetter("s", library), isNull);
}
@ -455,8 +437,7 @@ class ClassElementImplTest extends AbstractTypeSystemTest {
ClassElementImpl classB =
ElementFactory.classElement("B", interfaceTypeStar(classA));
classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classA, classB];
(library.definingCompilationUnit).classes = <ClassElement>[classA, classB];
expect(classA.lookUpSetter("s", library), isNull);
}
@ -516,8 +497,7 @@ class ElementImplTest extends AbstractTypeSystemTest {
void test_equals() {
LibraryElementImpl library = ElementFactory.library(analysisContext, "lib");
ClassElementImpl classElement = ElementFactory.classElement2("C");
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classElement];
(library.definingCompilationUnit).classes = <ClassElement>[classElement];
FieldElement field = ElementFactory.fieldElement(
"next",
false,
@ -541,8 +521,7 @@ class ElementImplTest extends AbstractTypeSystemTest {
LibraryElementImpl library1 =
ElementFactory.library(analysisContext, "lib1");
ClassElement classElement = ElementFactory.classElement2("_C");
(library1.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classElement];
(library1.definingCompilationUnit).classes = <ClassElement>[classElement];
LibraryElementImpl library2 =
ElementFactory.library(analysisContext, "lib2");
expect(classElement.isAccessibleIn(library2), isFalse);
@ -551,8 +530,7 @@ class ElementImplTest extends AbstractTypeSystemTest {
void test_isAccessibleIn_private_sameLibrary() {
LibraryElementImpl library = ElementFactory.library(analysisContext, "lib");
ClassElement classElement = ElementFactory.classElement2("_C");
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classElement];
(library.definingCompilationUnit).classes = <ClassElement>[classElement];
expect(classElement.isAccessibleIn(library), isTrue);
}
@ -560,8 +538,7 @@ class ElementImplTest extends AbstractTypeSystemTest {
LibraryElementImpl library1 =
ElementFactory.library(analysisContext, "lib1");
ClassElement classElement = ElementFactory.classElement2("C");
(library1.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classElement];
(library1.definingCompilationUnit).classes = <ClassElement>[classElement];
LibraryElementImpl library2 =
ElementFactory.library(analysisContext, "lib2");
expect(classElement.isAccessibleIn(library2), isTrue);
@ -570,8 +547,7 @@ class ElementImplTest extends AbstractTypeSystemTest {
void test_isAccessibleIn_public_sameLibrary() {
LibraryElementImpl library = ElementFactory.library(analysisContext, "lib");
ClassElement classElement = ElementFactory.classElement2("C");
(library.definingCompilationUnit as CompilationUnitElementImpl).classes =
<ClassElement>[classElement];
(library.definingCompilationUnit).classes = <ClassElement>[classElement];
expect(classElement.isAccessibleIn(library), isTrue);
}

View file

@ -38084,8 +38084,7 @@ library
Element _elementOfDefiningUnit(
LibraryElementImpl library, List<String> names) {
var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
var reference = unit.reference!;
var reference = library.definingCompilationUnit.reference!;
for (var name in names) {
reference = reference.getChild(name);
}

View file

@ -1091,6 +1091,58 @@ library
''');
}
test_declarationsPhase_unit_variables() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class MyMacro implements ClassDeclarationsMacro {
const MyMacro();
buildDeclarationsForClass(clazz, builder) async {
builder.declareInLibrary(
DeclarationCode.fromString('final x = 42;'),
);
}
}
const myMacro = MyMacro();
''');
var library = await buildLibrary(r'''
import 'a.dart';
@myMacro
class A {}
''', preBuildSequence: [
{'package:test/a.dart'}
]);
checkElementText(library, r'''
library
imports
package:test/a.dart
definingUnit
classes
class A @33
metadata
Annotation
atSign: @ @18
name: SimpleIdentifier
token: myMacro @19
staticElement: package:test/a.dart::@getter::myMacro
staticType: null
element: package:test/a.dart::@getter::myMacro
constructors
synthetic @-1
topLevelVariables
static final x @-1
type: int
accessors
synthetic static get x @-1
returnType: int
''');
}
test_introspect_types_ClassDeclaration_interfaces() async {
await _assertTypesPhaseIntrospectionText(r'''
class A implements B, C<int, String> {}