| Index: pkg/analyzer/lib/src/dart/analysis/analysis_impl.dart
|
| diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_impl.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_impl.dart
|
| index 3ca5096fbd3de09c426931d8758e4ec3547c00c2..4b656beda81c0d3998e7dffe9e57b39e4df979ff 100644
|
| --- a/pkg/analyzer/lib/src/dart/analysis/analysis_impl.dart
|
| +++ b/pkg/analyzer/lib/src/dart/analysis/analysis_impl.dart
|
| @@ -10,6 +10,8 @@ import 'package:analyzer/error/listener.dart';
|
| import 'package:analyzer/src/context/context.dart';
|
| import 'package:analyzer/src/dart/analysis/file_state.dart';
|
| import 'package:analyzer/src/dart/ast/ast.dart';
|
| +import 'package:analyzer/src/dart/constant/evaluation.dart';
|
| +import 'package:analyzer/src/dart/constant/utilities.dart';
|
| import 'package:analyzer/src/dart/element/element.dart';
|
| import 'package:analyzer/src/dart/scanner/scanner.dart';
|
| import 'package:analyzer/src/error/codes.dart';
|
| @@ -23,6 +25,7 @@ import 'package:analyzer/src/generated/source.dart';
|
| import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
| import 'package:analyzer/src/task/dart.dart';
|
| import 'package:analyzer/src/task/strong/checker.dart';
|
| +import 'package:front_end/src/dependency_walker.dart';
|
| import 'package:front_end/src/scanner/reader.dart';
|
|
|
| /**
|
| @@ -43,6 +46,7 @@ class AnalyzerImpl {
|
| final Map<FileState, ErrorReporter> _errorReporters = {};
|
| final List<UsedImportedElements> usedImportedElementsList = [];
|
| final List<UsedLocalElements> usedLocalElementsList = [];
|
| + final List<ConstantEvaluationTarget> _constants = [];
|
|
|
| AnalyzerImpl(
|
| this.analysisOptions, this.sourceFactory, this.fsState, this.store);
|
| @@ -76,6 +80,8 @@ class AnalyzerImpl {
|
| _resolveFile(analysisContext, library, file, unit);
|
| });
|
|
|
| + _computeConstants();
|
| +
|
| units.forEach((file, unit) {
|
| LibraryElement libraryElement = unit.element.library;
|
| {
|
| @@ -106,12 +112,115 @@ class AnalyzerImpl {
|
| return results;
|
| }
|
|
|
| + /**
|
| + * Compute [_constants] in all units.
|
| + */
|
| + void _computeConstants() {
|
| + ConstantEvaluationEngine evaluationEngine = new ConstantEvaluationEngine(
|
| + analysisContext.typeProvider, analysisContext.declaredVariables,
|
| + typeSystem: analysisContext.typeSystem);
|
| +
|
| + List<_ConstantNode> nodes = [];
|
| + Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {};
|
| + for (ConstantEvaluationTarget constant in _constants) {
|
| + var node = new _ConstantNode(evaluationEngine, nodeMap, constant);
|
| + nodes.add(node);
|
| + nodeMap[constant] = node;
|
| + }
|
| +
|
| + for (_ConstantNode node in nodes) {
|
| + if (!node.isEvaluated) {
|
| + new _ConstantWalker(evaluationEngine).walk(node);
|
| + }
|
| + }
|
| + }
|
| +
|
| void _computeVerifyErrorsAndHints(AnalysisContext analysisContext,
|
| FileState libraryFile, FileState file, CompilationUnit unit) {
|
| RecordingErrorListener errorListener = _getErrorListener(file);
|
| CompilationUnitElement unitElement = unit.element;
|
| LibraryElement libraryElement = unitElement.library;
|
|
|
| + //
|
| + // Use the ErrorVerifier to compute errors.
|
| + //
|
| + List<PendingError> pendingErrors;
|
| + {
|
| + RequiredConstantsComputer computer =
|
| + new RequiredConstantsComputer(file.source);
|
| + unit.accept(computer);
|
| + pendingErrors = computer.pendingErrors;
|
| + List<ConstantEvaluationTarget> requiredConstants =
|
| + computer.requiredConstants;
|
| + }
|
| +
|
| + if (analysisOptions.strongMode) {
|
| + AnalysisOptionsImpl options = analysisOptions as AnalysisOptionsImpl;
|
| + CodeChecker checker = new CodeChecker(
|
| + typeProvider,
|
| + new StrongTypeSystemImpl(typeProvider,
|
| + implicitCasts: options.implicitCasts,
|
| + nonnullableTypes: options.nonnullableTypes),
|
| + errorListener,
|
| + options);
|
| + checker.visitCompilationUnit(unit);
|
| + }
|
| +
|
| + var errorReporter = _getErrorReporter(file);
|
| +
|
| + //
|
| + // Validate the directives.
|
| + //
|
| + _validateUriBasedDirectives(file, unit);
|
| +
|
| + //
|
| + // Use the ConstantVerifier to compute errors.
|
| + //
|
| + ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
|
| + libraryElement, typeProvider, analysisContext.declaredVariables);
|
| + unit.accept(constantVerifier);
|
| +
|
| + //
|
| + // Use the ErrorVerifier to compute errors.
|
| + //
|
| + ErrorVerifier errorVerifier = new ErrorVerifier(
|
| + errorReporter,
|
| + libraryElement,
|
| + typeProvider,
|
| + new InheritanceManager(libraryElement),
|
| + analysisOptions.enableSuperMixins);
|
| + unit.accept(errorVerifier);
|
| +
|
| + //
|
| + // Convert the pending errors into actual errors.
|
| + //
|
| + for (PendingError pendingError in pendingErrors) {
|
| + errorListener.onError(pendingError.toAnalysisError());
|
| + }
|
| +
|
| + //
|
| + // Find dead code.
|
| + //
|
| + unit.accept(new DeadCodeVerifier(errorReporter,
|
| + typeSystem: analysisContext.typeSystem));
|
| +
|
| + // Dart2js analysis.
|
| + if (analysisOptions.dart2jsHint) {
|
| + unit.accept(new Dart2JSVerifier(errorReporter));
|
| + }
|
| +
|
| + InheritanceManager inheritanceManager = new InheritanceManager(
|
| + libraryElement,
|
| + includeAbstractFromSuperclasses: true);
|
| +
|
| + unit.accept(new BestPracticesVerifier(
|
| + errorReporter, typeProvider, libraryElement, inheritanceManager,
|
| + typeSystem: analysisContext.typeSystem));
|
| +
|
| + unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
|
| +
|
| + new ToDoFinder(errorReporter).findIn(unit);
|
| +
|
| // Verify imports.
|
| {
|
| ImportsVerifier verifier = new ImportsVerifier();
|
| @@ -180,8 +289,11 @@ class AnalyzerImpl {
|
| void _resolveFile(AnalysisContext analysisContext, FileState library,
|
| FileState file, CompilationUnit unit) {
|
| if (!file.exists) {
|
| - var unitElement = new CompilationUnitElementImpl(file.source.shortName);
|
| + Source source = file.source;
|
| + var unitElement = new CompilationUnitElementImpl(source.shortName);
|
| var libraryElement = new LibraryElementImpl(analysisContext, null, -1, 0);
|
| + unitElement.source = source;
|
| + unitElement.librarySource = source;
|
| libraryElement.definingCompilationUnit = unitElement;
|
| unit.element = unitElement;
|
| return;
|
| @@ -238,87 +350,14 @@ class AnalyzerImpl {
|
| unit.accept(new ResolverVisitor(
|
| libraryElement, unitElement.source, typeProvider, errorListener));
|
|
|
| - // TODO(scheglov) RESOLVED_UNIT12: compute constants
|
| -
|
| //
|
| - // Use the ErrorVerifier to compute errors.
|
| + // Find constants to compute.
|
| //
|
| - List<PendingError> pendingErrors;
|
| {
|
| - RequiredConstantsComputer computer =
|
| - new RequiredConstantsComputer(file.source);
|
| - unit.accept(computer);
|
| - pendingErrors = computer.pendingErrors;
|
| - List<ConstantEvaluationTarget> requiredConstants =
|
| - computer.requiredConstants;
|
| - }
|
| -
|
| - if (analysisOptions.strongMode) {
|
| - AnalysisOptionsImpl options = analysisOptions as AnalysisOptionsImpl;
|
| - CodeChecker checker = new CodeChecker(
|
| - typeProvider,
|
| - new StrongTypeSystemImpl(typeProvider,
|
| - implicitCasts: options.implicitCasts,
|
| - nonnullableTypes: options.nonnullableTypes),
|
| - errorListener,
|
| - options);
|
| - checker.visitCompilationUnit(unit);
|
| - }
|
| -
|
| - var errorReporter = _getErrorReporter(file);
|
| -
|
| - //
|
| - // Validate the directives.
|
| - //
|
| - _validateUriBasedDirectives(file, unit);
|
| -
|
| - //
|
| - // Use the ConstantVerifier to compute errors.
|
| - //
|
| - ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
|
| - libraryElement, typeProvider, analysisContext.declaredVariables);
|
| - unit.accept(constantVerifier);
|
| -
|
| - //
|
| - // Use the ErrorVerifier to compute errors.
|
| - //
|
| - ErrorVerifier errorVerifier = new ErrorVerifier(
|
| - errorReporter,
|
| - libraryElement,
|
| - typeProvider,
|
| - new InheritanceManager(libraryElement),
|
| - analysisOptions.enableSuperMixins);
|
| - unit.accept(errorVerifier);
|
| -
|
| - //
|
| - // Convert the pending errors into actual errors.
|
| - //
|
| - for (PendingError pendingError in pendingErrors) {
|
| - errorListener.onError(pendingError.toAnalysisError());
|
| + ConstantFinder constantFinder = new ConstantFinder();
|
| + unit.accept(constantFinder);
|
| + _constants.addAll(constantFinder.constantsToCompute);
|
| }
|
| -
|
| - //
|
| - // Find dead code.
|
| - //
|
| - unit.accept(new DeadCodeVerifier(errorReporter,
|
| - typeSystem: analysisContext.typeSystem));
|
| -
|
| - // Dart2js analysis.
|
| - if (analysisOptions.dart2jsHint) {
|
| - unit.accept(new Dart2JSVerifier(errorReporter));
|
| - }
|
| -
|
| - InheritanceManager inheritanceManager = new InheritanceManager(
|
| - libraryElement,
|
| - includeAbstractFromSuperclasses: true);
|
| -
|
| - unit.accept(new BestPracticesVerifier(
|
| - errorReporter, typeProvider, libraryElement, inheritanceManager,
|
| - typeSystem: analysisContext.typeSystem));
|
| -
|
| - unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
|
| -
|
| - new ToDoFinder(errorReporter).findIn(unit);
|
| }
|
|
|
| /**
|
| @@ -440,6 +479,60 @@ class UnitAnalysisResult {
|
| }
|
|
|
| /**
|
| + * [Node] that is used to compute constants in dependency order.
|
| + */
|
| +class _ConstantNode extends Node<_ConstantNode> {
|
| + final ConstantEvaluationEngine evaluationEngine;
|
| + final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
|
| + final ConstantEvaluationTarget constant;
|
| +
|
| + List<_ConstantNode> _dependencies = null;
|
| +
|
| + bool isEvaluated = false;
|
| +
|
| + _ConstantNode(this.evaluationEngine, this.nodeMap, this.constant);
|
| +
|
| + @override
|
| + List<_ConstantNode> computeDependencies() {
|
| + if (_dependencies == null) {
|
| + List<ConstantEvaluationTarget> targets = [];
|
| + evaluationEngine.computeDependencies(constant, targets.add);
|
| + _dependencies = targets.map(_getNode).toList();
|
| + }
|
| + return _dependencies;
|
| + }
|
| +
|
| + _ConstantNode _getNode(ConstantEvaluationTarget constant) {
|
| + return nodeMap.putIfAbsent(
|
| + constant, () => new _ConstantNode(evaluationEngine, nodeMap, constant));
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * [DependencyWalker] for computing constants and detecting cycles.
|
| + */
|
| +class _ConstantWalker extends DependencyWalker<_ConstantNode> {
|
| + final ConstantEvaluationEngine evaluationEngine;
|
| +
|
| + _ConstantWalker(this.evaluationEngine);
|
| +
|
| + @override
|
| + void evaluate(_ConstantNode node) {
|
| + evaluationEngine.computeConstantValue(node.constant);
|
| + node.isEvaluated = true;
|
| + }
|
| +
|
| + @override
|
| + void evaluateScc(List<_ConstantNode> scc) {
|
| + var constantsInCycle = scc.map((node) => node.constant);
|
| + for (_ConstantNode node in scc) {
|
| + evaluationEngine.generateCycleError(constantsInCycle, node.constant);
|
| + node.isEvaluated = true;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| * [ContentCache] wrapper around [FileContentOverlay].
|
| */
|
| class _ContentCacheWrapper implements ContentCache {
|
|
|