@@ -12,8 +12,8 @@ import 'package:analyzer/src/dart/analysis/experiments.dart';
1212import 'package:analyzer/src/dart/ast/ast.dart'
1313 show
1414 ClassDeclarationImpl,
15- ClassOrMixinDeclarationImpl,
1615 CompilationUnitImpl,
16+ ExtensionDeclarationImpl,
1717 MixinDeclarationImpl;
1818import 'package:analyzer/src/fasta/error_converter.dart' ;
1919import 'package:analyzer/src/generated/utilities_dart.dart' ;
@@ -86,6 +86,9 @@ class AstBuilder extends StackListener {
8686 /// The mixin currently being parsed, or `null` if no mixin is being parsed.
8787 MixinDeclarationImpl mixinDeclaration;
8888
89+ /// The extension currently being parsed, or `null` if none.
90+ ExtensionDeclarationImpl extensionDeclaration;
91+
8992 /// If true, this is building a full AST. Otherwise, only create method
9093 /// bodies.
9194 final bool isFullAst;
@@ -127,6 +130,26 @@ class AstBuilder extends StackListener {
127130 : this .errorReporter = new FastaErrorReporter (errorReporter),
128131 uri = uri ?? fileUri;
129132
133+ NodeList <ClassMember > get currentDeclarationMembers {
134+ if (classDeclaration != null ) {
135+ return classDeclaration.members;
136+ } else if (mixinDeclaration != null ) {
137+ return mixinDeclaration.members;
138+ } else {
139+ return extensionDeclaration.members;
140+ }
141+ }
142+
143+ SimpleIdentifier get currentDeclarationName {
144+ if (classDeclaration != null ) {
145+ return classDeclaration.name;
146+ } else if (mixinDeclaration != null ) {
147+ return mixinDeclaration.name;
148+ } else {
149+ return extensionDeclaration.name;
150+ }
151+ }
152+
130153 @override
131154 void addProblem (Message message, int charOffset, int length,
132155 {bool wasHandled: false , List <LocatedMessage > context}) {
@@ -155,7 +178,9 @@ class AstBuilder extends StackListener {
155178
156179 @override
157180 void beginClassDeclaration (Token begin, Token abstractToken, Token name) {
158- assert (classDeclaration == null && mixinDeclaration == null );
181+ assert (classDeclaration == null &&
182+ mixinDeclaration == null &&
183+ extensionDeclaration == null );
159184 push (new _Modifiers ()..abstractKeyword = abstractToken);
160185 }
161186
@@ -164,6 +189,30 @@ class AstBuilder extends StackListener {
164189 push (token);
165190 }
166191
192+ @override
193+ void beginExtensionDeclaration (Token extensionKeyword, Token nameToken) {
194+ assert (optional ('extension' , extensionKeyword));
195+ assert (classDeclaration == null &&
196+ mixinDeclaration == null &&
197+ extensionDeclaration == null );
198+ debugEvent ("ExtensionHeader" );
199+
200+ TypeParameterList typeParameters = pop ();
201+ SimpleIdentifier name = pop ();
202+ List <Annotation > metadata = pop ();
203+ Comment comment = _findComment (metadata, extensionKeyword);
204+
205+ extensionDeclaration = ast.extensionDeclaration (
206+ comment: comment,
207+ metadata: metadata,
208+ name: name,
209+ typeParameters: typeParameters,
210+ extendedType: null , // extendedType is set in [endExtensionDeclaration]
211+ ) as ExtensionDeclarationImpl ;
212+
213+ declarations.add (extensionDeclaration);
214+ }
215+
167216 @override
168217 void beginFactoryMethod (
169218 Token lastConsumed, Token externalToken, Token constToken) {
@@ -234,7 +283,9 @@ class AstBuilder extends StackListener {
234283
235284 @override
236285 void beginMixinDeclaration (Token mixinKeyword, Token name) {
237- assert (classDeclaration == null && mixinDeclaration == null );
286+ assert (classDeclaration == null &&
287+ mixinDeclaration == null &&
288+ extensionDeclaration == null );
238289 }
239290
240291 @override
@@ -481,14 +532,25 @@ class AstBuilder extends StackListener {
481532 @override
482533 void endClassOrMixinBody (
483534 int memberCount, Token leftBracket, Token rightBracket) {
535+ // TODO(danrubel): consider renaming endClassOrMixinBody
536+ // to endClassOrMixinOrExtensionBody
484537 assert (optional ('{' , leftBracket));
485538 assert (optional ('}' , rightBracket));
486539 debugEvent ("ClassOrMixinBody" );
487540
488- ClassOrMixinDeclarationImpl declaration =
489- classDeclaration ?? mixinDeclaration;
490- declaration.leftBracket = leftBracket;
491- declaration.rightBracket = rightBracket;
541+ if (classDeclaration != null ) {
542+ classDeclaration
543+ ..leftBracket = leftBracket
544+ ..rightBracket = rightBracket;
545+ } else if (mixinDeclaration != null ) {
546+ mixinDeclaration
547+ ..leftBracket = leftBracket
548+ ..rightBracket = rightBracket;
549+ } else {
550+ extensionDeclaration
551+ ..leftBracket = leftBracket
552+ ..rightBracket = rightBracket;
553+ }
492554 }
493555
494556 @override
@@ -642,6 +704,15 @@ class AstBuilder extends StackListener {
642704 configurations, combinators, semicolon));
643705 }
644706
707+ @override
708+ void endExtensionDeclaration (Token onKeyword, Token token) {
709+ TypeAnnotation type = pop ();
710+ extensionDeclaration
711+ ..extendedType = type
712+ ..onKeyword = onKeyword;
713+ extensionDeclaration = null ;
714+ }
715+
645716 @override
646717 void endFactoryMethod (
647718 Token beginToken, Token factoryKeyword, Token endToken) {
@@ -694,21 +765,20 @@ class AstBuilder extends StackListener {
694765 ast.simpleIdentifier (typeName.identifier.token, isDeclaration: true );
695766 }
696767
697- (classDeclaration ?? mixinDeclaration).members.add (
698- ast.constructorDeclaration (
699- comment,
700- metadata,
701- modifiers? .externalKeyword,
702- modifiers? .finalConstOrVarKeyword,
703- factoryKeyword,
704- ast.simpleIdentifier (returnType.token),
705- period,
706- name,
707- parameters,
708- separator,
709- null ,
710- redirectedConstructor,
711- body));
768+ currentDeclarationMembers.add (ast.constructorDeclaration (
769+ comment,
770+ metadata,
771+ modifiers? .externalKeyword,
772+ modifiers? .finalConstOrVarKeyword,
773+ factoryKeyword,
774+ ast.simpleIdentifier (returnType.token),
775+ period,
776+ name,
777+ parameters,
778+ separator,
779+ null ,
780+ redirectedConstructor,
781+ body));
712782 }
713783
714784 void endFieldInitializer (Token assignment, Token token) {
@@ -737,7 +807,7 @@ class AstBuilder extends StackListener {
737807 Token covariantKeyword = covariantToken;
738808 List <Annotation > metadata = pop ();
739809 Comment comment = _findComment (metadata, beginToken);
740- (classDeclaration ?? mixinDeclaration).members .add (ast.fieldDeclaration2 (
810+ currentDeclarationMembers .add (ast.fieldDeclaration2 (
741811 comment: comment,
742812 metadata: metadata,
743813 covariantKeyword: covariantKeyword,
@@ -1415,9 +1485,6 @@ class AstBuilder extends StackListener {
14151485 beginToken.charOffset, uri);
14161486 }
14171487
1418- ClassOrMixinDeclarationImpl declaration =
1419- classDeclaration ?? mixinDeclaration;
1420-
14211488 void constructor (
14221489 SimpleIdentifier prefixOrName, Token period, SimpleIdentifier name) {
14231490 if (typeParameters != null ) {
@@ -1453,7 +1520,7 @@ class AstBuilder extends StackListener {
14531520 initializers,
14541521 redirectedConstructor,
14551522 body);
1456- declaration.members .add (constructor);
1523+ currentDeclarationMembers .add (constructor);
14571524 if (mixinDeclaration != null ) {
14581525 // TODO (danrubel): Report an error if this is a mixin declaration.
14591526 }
@@ -1466,7 +1533,7 @@ class AstBuilder extends StackListener {
14661533 messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
14671534 }
14681535 checkFieldFormalParameters (parameters);
1469- declaration.members .add (ast.methodDeclaration (
1536+ currentDeclarationMembers .add (ast.methodDeclaration (
14701537 comment,
14711538 metadata,
14721539 modifiers? .externalKeyword,
@@ -1481,7 +1548,7 @@ class AstBuilder extends StackListener {
14811548 }
14821549
14831550 if (name is SimpleIdentifier ) {
1484- if (name.name == declaration.name .name && getOrSet == null ) {
1551+ if (name.name == currentDeclarationName .name && getOrSet == null ) {
14851552 constructor (name, null , null );
14861553 } else if (initializers.isNotEmpty && getOrSet == null ) {
14871554 constructor (name, null , null );
@@ -2683,7 +2750,9 @@ class AstBuilder extends StackListener {
26832750 @override
26842751 void handleMixinHeader (Token mixinKeyword) {
26852752 assert (optional ('mixin' , mixinKeyword));
2686- assert (classDeclaration == null && mixinDeclaration == null );
2753+ assert (classDeclaration == null &&
2754+ mixinDeclaration == null &&
2755+ extensionDeclaration == null );
26872756 debugEvent ("MixinHeader" );
26882757
26892758 ImplementsClause implementsClause = pop (NullValue .IdentifierList );
0 commit comments