blob: 149f8cec26c925109e2bacf6d3afa25945d14e36 [file] [log] [blame]
// Copyright (c) 2019, 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.
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/summary2/ast_resolver.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linking_node_scope.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
class DefaultValueResolver {
final Linker _linker;
final LibraryBuilder _libraryBuilder;
final TypeSystemImpl _typeSystem;
DefaultValueResolver(this._linker, this._libraryBuilder)
: _typeSystem = _libraryBuilder.element.typeSystem;
void resolve() {
for (var libraryFragment in _libraryBuilder.element.fragments) {
_UnitContext(libraryFragment)
..forEach(libraryFragment.classes, _interface)
..forEach(libraryFragment.enums, _interface)
..forEach(libraryFragment.extensions, _extension)
..forEach(libraryFragment.extensionTypes, _interface)
..forEach(libraryFragment.functions, _executable)
..forEach(libraryFragment.mixins, _interface);
}
}
void _constructor(_ClassContext context, ConstructorFragmentImpl element) {
if (element.isSynthetic) return;
_executable(context, element);
}
DefaultFormalParameterImpl? _defaultParameter(
FormalParameterFragmentImpl element,
) {
var node = _linker.getLinkingNode(element);
if (node is DefaultFormalParameterImpl && node.defaultValue != null) {
return node;
} else {
return null;
}
}
void _executable(_Context context, ExecutableFragmentImpl element) {
_ExecutableContext(
enclosingContext: context,
executableElement: element,
scope: _scopeFromElement(element),
).forEach(element.parameters, _parameter);
}
void _extension(_UnitContext context, ExtensionFragmentImpl element) {
context.forEach(element.methods, _executable);
}
void _interface(_UnitContext context, InterfaceFragmentImpl element) {
_ClassContext(context, element)
..forEach(element.constructors, _constructor)
..forEach(element.methods, _executable);
}
void _parameter(
_ExecutableContext context,
FormalParameterFragmentImpl parameter,
) {
// If a function typed parameter, process nested parameters.
context.forEach(parameter.parameters, _parameter);
var node = _defaultParameter(parameter);
if (node == null) return;
var contextType = _typeSystem.eliminateTypeVariables(parameter.type);
var analysisOptions = _libraryBuilder.kind.file.analysisOptions;
var astResolver = AstResolver(
_linker,
context.libraryFragment,
context.scope,
analysisOptions,
enclosingClassElement: context.classElement?.asElement2,
enclosingExecutableElement: context.executableElement.asElement2,
);
astResolver.resolveExpression(
() => node.defaultValue!,
contextType: contextType,
);
}
Scope _scopeFromElement(FragmentImpl element) {
var node = _linker.getLinkingNode(element)!;
return LinkingNodeContext.get(node).scope;
}
}
class _ClassContext extends _Context {
final _UnitContext unitContext;
@override
final InterfaceFragmentImpl classElement;
_ClassContext(this.unitContext, this.classElement);
@override
LibraryFragmentImpl get libraryFragment {
return unitContext.libraryFragment;
}
}
abstract class _Context {
InterfaceFragmentImpl? get classElement => null;
LibraryFragmentImpl get libraryFragment;
}
class _ExecutableContext extends _Context {
final _Context enclosingContext;
final ExecutableFragmentImpl executableElement;
final Scope scope;
_ExecutableContext({
required this.enclosingContext,
required this.executableElement,
required this.scope,
});
@override
InterfaceFragmentImpl? get classElement {
return enclosingContext.classElement;
}
@override
LibraryFragmentImpl get libraryFragment {
return enclosingContext.libraryFragment;
}
}
class _UnitContext extends _Context {
@override
final LibraryFragmentImpl libraryFragment;
_UnitContext(this.libraryFragment);
}
extension _ContextExtension<C extends _Context> on C {
void forEach<T>(List<T> elements, void Function(C context, T element) f) {
for (var element in elements) {
f(this, element);
}
}
}