Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Unified Diff: packages/analyzer/lib/src/dart/constant/utilities.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/analyzer/lib/src/dart/constant/utilities.dart
diff --git a/packages/analyzer/lib/src/dart/constant/utilities.dart b/packages/analyzer/lib/src/dart/constant/utilities.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d9ef263205735bf66a475e1d707682475e5572f3
--- /dev/null
+++ b/packages/analyzer/lib/src/dart/constant/utilities.dart
@@ -0,0 +1,320 @@
+// Copyright (c) 2014, 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.
+
+library analyzer.src.dart.constant.utilities;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/handle.dart'
+ show ConstructorElementHandle;
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/task/dart.dart';
+
+ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
+ while (constructor is ConstructorMember) {
+ constructor = (constructor as ConstructorMember).baseElement;
+ }
+ if (constructor is ConstructorElementHandle) {
+ constructor = (constructor as ConstructorElementHandle).actualElement;
+ }
+ return constructor;
+}
+
+/**
+ * Callback used by [ReferenceFinder] to report that a dependency was found.
+ */
+typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
+
+/**
+ * An [AstCloner] that copies the necessary information from the AST to allow
+ * constants to be evaluated.
+ */
+class ConstantAstCloner extends AstCloner {
+ ConstantAstCloner() : super(true);
+
+ @override
+ ConstructorName visitConstructorName(ConstructorName node) {
+ ConstructorName name = super.visitConstructorName(node);
+ name.staticElement = node.staticElement;
+ return name;
+ }
+
+ @override
+ Annotation visitAnnotation(Annotation node) {
+ Annotation annotation = super.visitAnnotation(node);
+ annotation.element = node.element;
+ return annotation;
+ }
+
+ @override
+ FunctionExpression visitFunctionExpression(FunctionExpression node) {
+ FunctionExpression expression = super.visitFunctionExpression(node);
+ expression.element = node.element;
+ return expression;
+ }
+
+ @override
+ InstanceCreationExpression visitInstanceCreationExpression(
+ InstanceCreationExpression node) {
+ InstanceCreationExpression expression =
+ super.visitInstanceCreationExpression(node);
+ expression.staticElement = node.staticElement;
+ return expression;
+ }
+
+ @override
+ RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ RedirectingConstructorInvocation invocation =
+ super.visitRedirectingConstructorInvocation(node);
+ invocation.staticElement = node.staticElement;
+ return invocation;
+ }
+
+ @override
+ SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+ SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
+ identifier.staticElement = node.staticElement;
+ return identifier;
+ }
+
+ @override
+ SuperConstructorInvocation visitSuperConstructorInvocation(
+ SuperConstructorInvocation node) {
+ SuperConstructorInvocation invocation =
+ super.visitSuperConstructorInvocation(node);
+ invocation.staticElement = node.staticElement;
+ return invocation;
+ }
+
+ @override
+ TypeName visitTypeName(TypeName node) {
+ TypeName typeName = super.visitTypeName(node);
+ typeName.type = node.type;
+ return typeName;
+ }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build the full set of dependencies for all constant
+ * expressions.
+ */
+class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
+ /**
+ * The constants whose values need to be computed.
+ */
+ HashSet<ConstantEvaluationTarget> dependencies =
+ new HashSet<ConstantEvaluationTarget>();
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (node.isConst) {
+ _find(node);
+ } else {
+ super.visitInstanceCreationExpression(node);
+ }
+ }
+
+ @override
+ void visitListLiteral(ListLiteral node) {
+ if (node.constKeyword != null) {
+ _find(node);
+ } else {
+ super.visitListLiteral(node);
+ }
+ }
+
+ @override
+ void visitMapLiteral(MapLiteral node) {
+ if (node.constKeyword != null) {
+ _find(node);
+ } else {
+ super.visitMapLiteral(node);
+ }
+ }
+
+ @override
+ void visitSwitchCase(SwitchCase node) {
+ _find(node.expression);
+ node.statements.accept(this);
+ }
+
+ void _find(Expression node) {
+ if (node != null) {
+ ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
+ node.accept(referenceFinder);
+ }
+ }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build tables of the constant variables, constant
+ * constructors, constant constructor invocations, and annotations found in
+ * those compilation units.
+ */
+class ConstantFinder extends RecursiveAstVisitor<Object> {
+ /**
+ * The elements and AST nodes whose constant values need to be computed.
+ */
+ List<ConstantEvaluationTarget> constantsToCompute =
+ <ConstantEvaluationTarget>[];
+
+ /**
+ * A flag indicating whether instance variables marked as "final" should be
+ * treated as "const".
+ */
+ bool treatFinalInstanceVarAsConst = false;
+
+ @override
+ Object visitAnnotation(Annotation node) {
+ super.visitAnnotation(node);
+ ElementAnnotation elementAnnotation = node.elementAnnotation;
+ if (elementAnnotation == null) {
+ // Analyzer ignores annotations on "part of" directives and on enum
+ // constant declarations.
+ assert(node.parent is PartOfDirective ||
+ node.parent is EnumConstantDeclaration);
+ } else {
+ constantsToCompute.add(elementAnnotation);
+ }
+ return null;
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
+ if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
+ // Instance vars marked "final" need to be included in the dependency
+ // graph, since constant constructors implicitly use the values in their
+ // initializers.
+ treatFinalInstanceVarAsConst = true;
+ }
+ try {
+ return super.visitClassDeclaration(node);
+ } finally {
+ treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
+ }
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ super.visitConstructorDeclaration(node);
+ if (node.constKeyword != null) {
+ ConstructorElement element = node.element;
+ if (element != null) {
+ constantsToCompute.add(element);
+ constantsToCompute.addAll(element.parameters);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+ super.visitDefaultFormalParameter(node);
+ Expression defaultValue = node.defaultValue;
+ if (defaultValue != null && node.element != null) {
+ constantsToCompute.add(node.element);
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ super.visitVariableDeclaration(node);
+ Expression initializer = node.initializer;
+ VariableElement element = node.element;
+ if (initializer != null &&
+ (node.isConst ||
+ treatFinalInstanceVarAsConst &&
+ element is FieldElement &&
+ node.isFinal &&
+ !element.isStatic)) {
+ if (element != null) {
+ constantsToCompute.add(element);
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * An object used to add reference information for a given variable to the
+ * bi-directional mapping used to order the evaluation of constants.
+ */
+class ReferenceFinder extends RecursiveAstVisitor<Object> {
+ /**
+ * The callback which should be used to report any dependencies that were
+ * found.
+ */
+ final ReferenceFinderCallback _callback;
+
+ /**
+ * Initialize a newly created reference finder to find references from a given
+ * variable to other variables and to add those references to the given graph.
+ * The [_callback] will be invoked for every dependency found.
+ */
+ ReferenceFinder(this._callback);
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (node.isConst) {
+ ConstructorElement constructor = getConstructorImpl(node.staticElement);
+ if (constructor != null) {
+ _callback(constructor);
+ }
+ }
+ return super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ Object visitLabel(Label node) {
+ // We are visiting the "label" part of a named expression in a function
+ // call (presumably a constructor call), e.g. "const C(label: ...)". We
+ // don't want to visit the SimpleIdentifier for the label because that's a
+ // reference to a function parameter that needs to be filled in; it's not a
+ // constant whose value we depend on.
+ return null;
+ }
+
+ @override
+ Object visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ super.visitRedirectingConstructorInvocation(node);
+ ConstructorElement target = getConstructorImpl(node.staticElement);
+ if (target != null) {
+ _callback(target);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ Element staticElement = node.staticElement;
+ Element element = staticElement is PropertyAccessorElement
+ ? staticElement.variable
+ : staticElement;
+ if (element is VariableElement && element.isConst) {
+ _callback(element);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ super.visitSuperConstructorInvocation(node);
+ ConstructorElement constructor = getConstructorImpl(node.staticElement);
+ if (constructor != null) {
+ _callback(constructor);
+ }
+ return null;
+ }
+}
« no previous file with comments | « packages/analyzer/lib/src/dart/constant/evaluation.dart ('k') | packages/analyzer/lib/src/dart/constant/value.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698