blob: abedb68e9bacd21ea383e6b7f458eec3d2ee7d68 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// This library provides additional APIs for the corresponding client.
///
/// By providing such higher level APIs we simplify the clients, and reduce
/// dependencies on analyzer internal, so can make otherwise breaking
/// changes easily.
library angular_analyzer_plugin;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/scope.dart';
import 'package:analyzer/src/dart/resolver/resolution_visitor.dart';
import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
/// Resolve the given [node] in the specified context.
///
/// The [componentClass] is the component class.
///
/// The [templateSource] is the file with the template.
///
/// The template might declare [localVariables], which might be referenced
/// in the node being resolved.
///
/// The [overrideAsExpression] is invoked during [AsExpression] to support
/// custom resolution behavior.
void resolveTemplateNode({
@required ClassElement componentClass,
@required Source templateSource,
@required Iterable<LocalVariableElement> localVariables,
@required AstNode node,
@required AnalysisErrorListener errorListener,
@required ErrorReporter errorReporter,
OverrideAsExpression overrideAsExpression,
}) {
final unitElement = componentClass.enclosingElement;
final library = componentClass.library;
node.accept(
ResolutionVisitor(
unitElement: unitElement,
errorListener: errorListener,
featureSet: library.context.analysisOptions.contextFeatures,
nameScope: library.scope,
),
);
final inheritanceManager = InheritanceManager3();
final resolver = _AngularTemplateResolver(inheritanceManager, library,
templateSource, library.typeProvider, errorListener,
overrideAsExpression: overrideAsExpression);
// fill the name scope
final classScope = ClassScope(resolver.nameScope, componentClass);
final localScope = LocalScope(classScope);
resolver
..nameScope = localScope
..enclosingClass = componentClass;
localVariables.forEach(localScope.add);
// do resolve
node.accept(resolver);
// verify
final verifier = ErrorVerifier(
errorReporter, library, library.typeProvider, inheritanceManager)
..enclosingClass = componentClass;
node.accept(verifier);
}
typedef OverrideAsExpression = void Function({
@required AsExpression node,
@required void Function(AsExpression) invokeSuper,
});
class _AngularTemplateResolver extends ResolverVisitor {
final OverrideAsExpression overrideAsExpression;
_AngularTemplateResolver(
InheritanceManager3 inheritanceManager,
LibraryElement library,
Source source,
TypeProvider typeProvider,
AnalysisErrorListener errorListener, {
@required this.overrideAsExpression,
}) : super(inheritanceManager, library, source, typeProvider, errorListener);
@override
void visitAsExpression(AsExpression node) {
if (overrideAsExpression != null) {
overrideAsExpression(
node: node,
invokeSuper: (node) {
super.visitAsExpression(node);
},
);
} else {
super.visitAsExpression(node);
}
}
}