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

Unified Diff: packages/analyzer/tool/summary/dump_inferred_types.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
« no previous file with comments | « packages/analyzer/tool/summary/check_test.dart ('k') | packages/analyzer/tool/summary/generate.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/analyzer/tool/summary/dump_inferred_types.dart
diff --git a/packages/analyzer/tool/summary/dump_inferred_types.dart b/packages/analyzer/tool/summary/dump_inferred_types.dart
new file mode 100644
index 0000000000000000000000000000000000000000..676ecd6293dbf9097b4fd0a21c665f1479dd1ea6
--- /dev/null
+++ b/packages/analyzer/tool/summary/dump_inferred_types.dart
@@ -0,0 +1,339 @@
+// Copyright (c) 2016, 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 'dart:convert';
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+
+/**
+ * Collect the inferred types from all the summary files listed in [args] and
+ * print them in alphabetical order.
+ */
+main(List<String> args) {
+ SummaryDataStore summaryDataStore = new SummaryDataStore(args);
+ InferredTypeCollector collector = new InferredTypeCollector(
+ (String uri) => summaryDataStore.linkedMap[uri],
+ (String uri) => summaryDataStore.unlinkedMap[uri]);
+ collector.visitSummaryDataStore(summaryDataStore);
+ collector.dumpCollectedTypes();
+}
+
+/**
+ * Visitor class that visits the contents of a summary file and collects the
+ * inferred types in it.
+ */
+class InferredTypeCollector {
+ UnlinkedUnit unlinkedUnit;
+ LinkedUnit linkedUnit;
+ CompilationUnitElementForLink unitForLink;
+ final Map<String, String> inferredTypes = <String, String>{};
+ List<String> typeParamsInScope = <String>[];
+ final Linker _linker;
+
+ InferredTypeCollector(
+ GetDependencyCallback getDependency, GetUnitCallback getUnit)
+ : _linker = new Linker({}, getDependency, getUnit, true);
+
+ /**
+ * If an inferred type exists matching the given [slot], record that it is the
+ * type of the entity reachable via [path].
+ */
+ void collectInferredType(int slot, String path) {
+ for (EntityRef type in linkedUnit.types) {
+ if (type.slot == slot) {
+ inferredTypes[path] = formatType(type);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Collect the inferred type in summary object [obj] (if any), which is
+ * reachable via [path].
+ *
+ * This method may modify [properties] in order to affect how sub-elements
+ * are visited.
+ */
+ void collectInferredTypes(
+ SummaryClass obj, Map<String, Object> properties, String path) {
+ if (obj is UnlinkedVariable) {
+ collectInferredType(obj.inferredTypeSlot, path);
+ // As a temporary measure, prevent recursion into the variable's
+ // initializer, since AST-based type inference doesn't infer its type
+ // correctly yet. TODO(paulberry): fix.
+ properties.remove('initializer');
+ } else if (obj is UnlinkedExecutable) {
+ collectInferredType(obj.inferredReturnTypeSlot, path);
+ // As a temporary measure, prevent recursion into the executable's local
+ // variables and local functions, since AST-based type inference doesn't
+ // infer locals correctly yet. TODO(paulberry): fix if necessary.
+ properties.remove('localFunctions');
+ properties.remove('localVariables');
+ } else if (obj is UnlinkedParam) {
+ collectInferredType(obj.inferredTypeSlot, path);
+ // As a temporary measure, prevent recursion into the parameter's
+ // initializer, since AST-based type inference doesn't infer its type
+ // correctly yet. TODO(paulberry): fix.
+ properties.remove('initializer');
+ }
+ }
+
+ /**
+ * Print out all the inferred types collected so far, in alphabetical order.
+ */
+ void dumpCollectedTypes() {
+ print('Collected types (${inferredTypes.length}):');
+ List<String> paths = inferredTypes.keys.toList();
+ paths.sort();
+ for (String path in paths) {
+ print('$path -> ${inferredTypes[path]}');
+ }
+ }
+
+ /**
+ * Format the given [type] as a string. Unlike the type's [toString] method,
+ * this formats types using their complete URI to avoid ambiguity.
+ */
+ String formatDartType(DartType type) {
+ if (type is FunctionType) {
+ List<String> argStrings =
+ type.normalParameterTypes.map(formatDartType).toList();
+ List<DartType> optionalParameterTypes = type.optionalParameterTypes;
+ if (optionalParameterTypes.isNotEmpty) {
+ List<String> optionalArgStrings =
+ optionalParameterTypes.map(formatDartType).toList();
+ argStrings.add('[${optionalArgStrings.join(', ')}]');
+ }
+ Map<String, DartType> namedParameterTypes = type.namedParameterTypes;
+ if (namedParameterTypes.isNotEmpty) {
+ List<String> namedArgStrings = <String>[];
+ namedParameterTypes.forEach((String name, DartType type) {
+ namedArgStrings.add('$name: ${formatDartType(type)}');
+ });
+ argStrings.add('{${namedArgStrings.join(', ')}}');
+ }
+ return '(${argStrings.join(', ')}) → ${formatDartType(type.returnType)}';
+ } else if (type is InterfaceType) {
+ if (type.typeArguments.isNotEmpty) {
+ // TODO(paulberry): implement.
+ throw new UnimplementedError('type args');
+ }
+ return formatElement(type.element);
+ } else if (type is DynamicTypeImpl) {
+ return type.toString();
+ } else {
+ // TODO(paulberry): implement.
+ throw new UnimplementedError(
+ "Don't know how to format type of type ${type.runtimeType}");
+ }
+ }
+
+ /**
+ * Format the given [element] as a string, assuming it represents a type.
+ * Unlike the element's [toString] method, this formats elements using their
+ * complete URI to avoid ambiguity.
+ */
+ String formatElement(Element element) {
+ if (element is ClassElementForLink_Class ||
+ element is MethodElementForLink ||
+ element is ClassElementForLink_Enum ||
+ element is SpecialTypeElementForLink ||
+ element is FunctionTypeAliasElementForLink ||
+ element is TopLevelFunctionElementForLink) {
+ return element.toString();
+ } else if (element is FunctionElementForLink_Local_NonSynthetic) {
+ return formatDartType(element.type);
+ } else if (element is UndefinedElementForLink) {
+ return '???';
+ } else {
+ throw new UnimplementedError(
+ "Don't know how to format reference of type ${element.runtimeType}");
+ }
+ }
+
+ /**
+ * Interpret the given [param] as a parameter in a synthetic typedef, and
+ * format it as a string.
+ */
+ String formatParam(UnlinkedParam param) {
+ if (param.isFunctionTyped) {
+ // TODO(paulberry): fix this case.
+ return 'BAD(${JSON.encode(param)})';
+ }
+ String result;
+ if (param.type != null) {
+ result = '${formatType(param.type)} ${param.name}';
+ } else {
+ result = param.name;
+ }
+ if (param.kind == UnlinkedParamKind.named) {
+ result = '{$result}';
+ } else if (param.kind == UnlinkedParamKind.positional) {
+ result = '[$result]';
+ }
+ return result;
+ }
+
+ /**
+ * Convert the reference with index [index] into a string. If [typeOf] is
+ * `true`, the reference is being used in the context of naming a type, so
+ * if the entity being referenced is not a type, it will be enclosed in
+ * `typeof()` for clarity.
+ */
+ String formatReference(int index, {bool typeOf: false}) {
+ ReferenceableElementForLink element = unitForLink.resolveRef(index);
+ return formatElement(element);
+ }
+
+ /**
+ * Interpret the given [entityRef] as a reference to a type, and format it as
+ * a string.
+ */
+ String formatType(EntityRef entityRef) {
+ List<int> implicitFunctionTypeIndices =
+ entityRef.implicitFunctionTypeIndices;
+ if (entityRef.syntheticReturnType != null) {
+ String params = entityRef.syntheticParams.map(formatParam).join(', ');
+ String retType = formatType(entityRef.syntheticReturnType);
+ return '($params) -> $retType';
+ }
+ if (entityRef.paramReference != 0) {
+ return typeParamsInScope[
+ typeParamsInScope.length - entityRef.paramReference];
+ }
+ String result = formatReference(entityRef.reference, typeOf: true);
+ List<EntityRef> typeArguments = entityRef.typeArguments.toList();
+ while (typeArguments.isNotEmpty && isDynamic(typeArguments.last)) {
+ typeArguments.removeLast();
+ }
+ if (typeArguments.isNotEmpty) {
+ result += '<${typeArguments.map(formatType).join(', ')}>';
+ }
+ if (implicitFunctionTypeIndices.isNotEmpty) {
+ result =
+ 'parameterOf($result, ${implicitFunctionTypeIndices.join(', ')})';
+ }
+ return result;
+ }
+
+ /**
+ * Determine if the given [entityRef] represents the pseudo-type `dynamic`.
+ */
+ bool isDynamic(EntityRef entityRef) {
+ if (entityRef.syntheticReturnType != null ||
+ entityRef.paramReference != 0) {
+ return false;
+ }
+ return formatReference(entityRef.reference, typeOf: true) == 'dynamic';
+ }
+
+ /**
+ * Collect all the inferred types contained in [obj], which is reachable via
+ * [path]. [properties] is the result of calling `obj.toMap()`, and may be
+ * modified before returning.
+ */
+ void visit(SummaryClass obj, Map<String, Object> properties, String path) {
+ List<String> oldTypeParamsInScope = typeParamsInScope;
+ Object newTypeParams = properties['typeParameters'];
+ if (newTypeParams is List && newTypeParams.isNotEmpty) {
+ typeParamsInScope = typeParamsInScope.toList();
+ for (Object typeParam in newTypeParams) {
+ if (typeParam is UnlinkedTypeParam) {
+ typeParamsInScope.add(typeParam.name);
+ } else {
+ throw new StateError(
+ 'Unexpected type param type: ${typeParam.runtimeType}');
+ }
+ }
+ }
+ collectInferredTypes(obj, properties, path);
+ properties.forEach((String key, Object value) {
+ if (value is SummaryClass) {
+ visit(value, value.toMap(), '$path.$key');
+ } else if (value is List) {
+ for (int i = 0; i < value.length; i++) {
+ Object item = value[i];
+ if (item is SummaryClass) {
+ Map<String, Object> itemProperties = item.toMap();
+ String indexOrName = itemProperties['name'] ?? i.toString();
+ visit(item, itemProperties, '$path.$key[$indexOrName]');
+ }
+ }
+ }
+ });
+ typeParamsInScope = oldTypeParamsInScope;
+ }
+
+ /**
+ * Collect all the inferred types contained in [summaryDataStore].
+ */
+ void visitSummaryDataStore(SummaryDataStore summaryDataStore) {
+ // Figure out which unlinked units are a part of another library so we won't
+ // visit them redundantly.
+ Set<String> partOfUris = new Set<String>();
+ summaryDataStore.unlinkedMap
+ .forEach((String unitUriString, UnlinkedUnit unlinkedUnit) {
+ Uri unitUri = Uri.parse(unitUriString);
+ for (String relativePartUriString in unlinkedUnit.publicNamespace.parts) {
+ partOfUris.add(
+ resolveRelativeUri(unitUri, Uri.parse(relativePartUriString))
+ .toString());
+ }
+ });
+ summaryDataStore.linkedMap
+ .forEach((String libraryUriString, LinkedLibrary linkedLibrary) {
+ if (partOfUris.contains(libraryUriString)) {
+ return;
+ }
+ if (libraryUriString.startsWith('dart:')) {
+ // Don't bother dumping inferred types from the SDK.
+ return;
+ }
+ Uri libraryUri = Uri.parse(libraryUriString);
+ UnlinkedUnit definingUnlinkedUnit =
+ summaryDataStore.unlinkedMap[libraryUriString];
+ if (definingUnlinkedUnit != null) {
+ visitUnit(
+ definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString, 0);
+ for (int i = 0;
+ i < definingUnlinkedUnit.publicNamespace.parts.length;
+ i++) {
+ Uri relativePartUri =
+ Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
+ String unitUriString =
+ resolveRelativeUri(libraryUri, relativePartUri).toString();
+ UnlinkedUnit unlinkedUnit =
+ summaryDataStore.unlinkedMap[unitUriString];
+ if (unlinkedUnit != null) {
+ visitUnit(unlinkedUnit, linkedLibrary.units[i + 1],
+ libraryUriString, i + 1);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Collect all the inferred types contained in the compilation unit described
+ * by [unlinkedUnit] and [linkedUnit], which has URI [libraryUriString].
+ */
+ void visitUnit(UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit,
+ String libraryUriString, int unitNum) {
+ this.unlinkedUnit = unlinkedUnit;
+ this.linkedUnit = linkedUnit;
+ this.unitForLink =
+ _linker.getLibrary(Uri.parse(libraryUriString)).units[unitNum];
+ visit(unlinkedUnit, unlinkedUnit.toMap(), libraryUriString);
+ this.unlinkedUnit = null;
+ this.linkedUnit = null;
+ this.unitForLink = null;
+ }
+}
« no previous file with comments | « packages/analyzer/tool/summary/check_test.dart ('k') | packages/analyzer/tool/summary/generate.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698