Index: pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart |
diff --git a/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart b/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart |
index 983ab80a9a84b72d8b3519b06bd2d73670478171..3e1880991910394f42f155ea40ee556183c7c9be 100644 |
--- a/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart |
+++ b/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart |
@@ -69,14 +69,13 @@ class AnalyzerDietListener extends DietListener { |
CoreTypes coreTypes, TypeInferenceEngine typeInferenceEngine) |
: super(library, hierarchy, coreTypes, typeInferenceEngine); |
- @override |
- void buildFunctionBody( |
- Token token, ProcedureBuilder builder, MemberKind kind, Token metadata) { |
- Scope typeParameterScope = builder.computeTypeParameterScope(memberScope); |
- Scope formalParameterScope = |
- builder.computeFormalParameterScope(typeParameterScope); |
- assert(typeParameterScope != null); |
- assert(formalParameterScope != null); |
+ /// Calls the parser (via [parserCallback]) using a body builder initialized |
+ /// to do type inference for the given [builder]. |
+ /// |
+ /// When parsing methods, [formalParameterScope] should be set to the formal |
+ /// parameter scope; otherwise it should be `null`. |
+ void _withBodyBuilder(ModifierBuilder builder, Scope formalParameterScope, |
+ void parserCallback()) { |
// Create a body builder to do type inference, and a listener to record the |
// types that are inferred. |
_kernelTypes = <kernel.DartType>[]; |
@@ -85,21 +84,48 @@ class AnalyzerDietListener extends DietListener { |
new InstrumentedResolutionStorer(_kernelTypes, _typeOffsets); |
_bodyBuilder = super.createListener(builder, memberScope, |
builder.isInstanceMember, formalParameterScope, resolutionStorer); |
- // Parse the function body normally; this will build the analyzer AST, run |
+ // Run the parser callback; this will build the analyzer AST, run |
// the body builder to do type inference, and then copy the inferred types |
// over to the analyzer AST. |
- parseFunctionBody( |
- createListener(builder, typeParameterScope, builder.isInstanceMember, |
- formalParameterScope), |
- token, |
- metadata, |
- kind); |
+ parserCallback(); |
// The inferred types and the body builder are no longer needed. |
_bodyBuilder = null; |
_kernelTypes = null; |
_typeOffsets = null; |
} |
+ @override |
+ void buildFields(int count, Token token, bool isTopLevel) { |
+ List<String> names = popList(count); |
+ Builder builder = lookupBuilder(token, null, names.first); |
+ Token metadata = pop(); |
+ _withBodyBuilder(builder, null, () { |
+ parseFields( |
+ createListener(builder, memberScope, builder.isInstanceMember), |
+ token, |
+ metadata, |
+ isTopLevel); |
+ }); |
+ } |
+ |
+ @override |
+ void buildFunctionBody( |
+ Token token, ProcedureBuilder builder, MemberKind kind, Token metadata) { |
+ Scope typeParameterScope = builder.computeTypeParameterScope(memberScope); |
+ Scope formalParameterScope = |
+ builder.computeFormalParameterScope(typeParameterScope); |
+ assert(typeParameterScope != null); |
+ assert(formalParameterScope != null); |
+ _withBodyBuilder(builder, formalParameterScope, () { |
+ parseFunctionBody( |
+ createListener(builder, typeParameterScope, builder.isInstanceMember, |
+ formalParameterScope), |
+ token, |
+ metadata, |
+ kind); |
+ }); |
+ } |
+ |
StackListener createListener( |
ModifierBuilder builder, Scope memberScope, bool isInstanceMember, |
[Scope formalParameterScope, TypeInferenceListener listener]) { |
@@ -154,6 +180,36 @@ class AnalyzerDietListener extends DietListener { |
listener.finishFunction(metadataConstants, formals, asyncModifier, body); |
} |
+ @override |
+ void listenerFinishFields( |
+ StackListener listener, Token token, Token metadata, bool isTopLevel) { |
+ // TODO(paulberry): this duplicates a lot of code from |
+ // DietListener.parseFields. |
+ |
+ // At this point the analyzer AST has been built, but it doesn't contain |
+ // resolution data or inferred types. Run the body builder and gather |
+ // this information. |
+ Parser parser = new Parser(_bodyBuilder); |
+ if (isTopLevel) { |
+ // There's a slight asymmetry between [parseTopLevelMember] and |
+ // [parseMember] because the former doesn't call `parseMetadataStar`. |
+ token = parser.parseMetadataStar(metadata ?? token); |
+ token = parser.parseTopLevelMember(token); |
+ } else { |
+ token = parser.parseMember(metadata ?? token); |
+ } |
+ _bodyBuilder.finishFields(); |
+ _bodyBuilder.checkEmpty(token.charOffset); |
+ |
+ // Now apply the resolution data and inferred types to the analyzer AST. |
+ var translatedTypes = _translateTypes(_kernelTypes); |
+ var resolutionApplier = |
+ new ValidatingResolutionApplier(translatedTypes, _typeOffsets); |
+ ast.AstNode fields = listener.finishFields(); |
+ fields.accept(resolutionApplier); |
+ resolutionApplier.checkDone(); |
+ } |
+ |
/// Translates the given kernel types into analyzer types. |
static List<ast.DartType> _translateTypes(List<kernel.DartType> kernelTypes) { |
// For now we just translate everything to `dynamic`. |