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

Side by Side Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1963593003: Implement 'instantiate to bounds' feature in resynthesizer. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fixes for review comments. Created 4 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library summary_resynthesizer; 5 library summary_resynthesizer;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 return AstFactory.identifier(enclosing, identifier); 514 return AstFactory.identifier(enclosing, identifier);
515 } 515 }
516 SimpleIdentifier property = AstFactory.identifier3(info.name) 516 SimpleIdentifier property = AstFactory.identifier3(info.name)
517 ..staticElement = element; 517 ..staticElement = element;
518 return AstFactory.propertyAccess(enclosing, property); 518 return AstFactory.propertyAccess(enclosing, property);
519 } 519 }
520 520
521 TypeName _buildTypeAst(DartType type) { 521 TypeName _buildTypeAst(DartType type) {
522 List<TypeName> argumentNodes; 522 List<TypeName> argumentNodes;
523 if (type is ParameterizedType) { 523 if (type is ParameterizedType) {
524 List<DartType> typeArguments = type.typeArguments; 524 if (!resynthesizer.libraryResynthesizer.typesWithImplicitTypeArguments
525 argumentNodes = typeArguments.every((a) => a.isDynamic) 525 .contains(type)) {
526 ? null 526 List<DartType> typeArguments = type.typeArguments;
527 : typeArguments.map(_buildTypeAst).toList(); 527 argumentNodes = typeArguments.every((a) => a.isDynamic)
528 ? null
529 : typeArguments.map(_buildTypeAst).toList();
530 }
528 } 531 }
529 TypeName node = AstFactory.typeName4(type.name, argumentNodes); 532 TypeName node = AstFactory.typeName4(type.name, argumentNodes);
530 node.type = type; 533 node.type = type;
531 (node.name as SimpleIdentifier).staticElement = type.element; 534 (node.name as SimpleIdentifier).staticElement = type.element;
532 return node; 535 return node;
533 } 536 }
534 537
535 PropertyAccessorElement _getStringLengthElement() => 538 PropertyAccessorElement _getStringLengthElement() =>
536 resynthesizer.typeProvider.stringType.getGetter('length'); 539 resynthesizer.typeProvider.stringType.getGetter('length');
537 540
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 <String, CompilationUnitElement>{}; 946 <String, CompilationUnitElement>{};
944 947
945 /** 948 /**
946 * Map of top level elements that have been resynthesized so far. The first 949 * Map of top level elements that have been resynthesized so far. The first
947 * key is the URI of the compilation unit; the second is the name of the top 950 * key is the URI of the compilation unit; the second is the name of the top
948 * level element. 951 * level element.
949 */ 952 */
950 final Map<String, Map<String, Element>> resynthesizedElements = 953 final Map<String, Map<String, Element>> resynthesizedElements =
951 <String, Map<String, Element>>{}; 954 <String, Map<String, Element>>{};
952 955
956 /**
957 * Types with implicit type arguments, which are the same as type parameter
958 * bounds (in strong mode), or `dynamic` (in spec mode).
959 */
960 final Set<DartType> typesWithImplicitTypeArguments =
961 new Set<DartType>.identity();
962
953 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, 963 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
954 this.unlinkedUnits, this.librarySource) { 964 this.unlinkedUnits, this.librarySource) {
955 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; 965 isCoreLibrary = librarySource.uri.toString() == 'dart:core';
956 } 966 }
957 967
958 /** 968 /**
959 * Resynthesize a [NamespaceCombinator]. 969 * Resynthesize a [NamespaceCombinator].
960 */ 970 */
961 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) { 971 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
962 if (serializedCombinator.shows.isNotEmpty) { 972 if (serializedCombinator.shows.isNotEmpty) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 } 1290 }
1281 } 1291 }
1282 1292
1283 /** 1293 /**
1284 * Data structure used during resynthesis to record all the information that is 1294 * Data structure used during resynthesis to record all the information that is
1285 * known about how to resynthesize a single entry in [LinkedUnit.references] 1295 * known about how to resynthesize a single entry in [LinkedUnit.references]
1286 * (and its associated entry in [UnlinkedUnit.references], if it exists). 1296 * (and its associated entry in [UnlinkedUnit.references], if it exists).
1287 */ 1297 */
1288 class _ReferenceInfo { 1298 class _ReferenceInfo {
1289 /** 1299 /**
1300 * The [_LibraryResynthesizer] which is being used to obtain summaries.
1301 */
1302 final _LibraryResynthesizer libraryResynthesizer;
1303
1304 /**
1290 * The enclosing [_ReferenceInfo], or `null` for top-level elements. 1305 * The enclosing [_ReferenceInfo], or `null` for top-level elements.
1291 */ 1306 */
1292 final _ReferenceInfo enclosing; 1307 final _ReferenceInfo enclosing;
1293 1308
1294 /** 1309 /**
1295 * The name of the entity referred to by this reference. 1310 * The name of the entity referred to by this reference.
1296 */ 1311 */
1297 final String name; 1312 final String name;
1298 1313
1299 /** 1314 /**
(...skipping 17 matching lines...) Expand all
1317 1332
1318 /** 1333 /**
1319 * Create a new [_ReferenceInfo] object referring to an element called [name] 1334 * Create a new [_ReferenceInfo] object referring to an element called [name]
1320 * via the element handle [element], and having [numTypeParameters] type 1335 * via the element handle [element], and having [numTypeParameters] type
1321 * parameters. 1336 * parameters.
1322 * 1337 *
1323 * For the special types `dynamic` and `void`, [specialType] should point to 1338 * For the special types `dynamic` and `void`, [specialType] should point to
1324 * the type itself. Otherwise, pass `null` and the type will be computed 1339 * the type itself. Otherwise, pass `null` and the type will be computed
1325 * when appropriate. 1340 * when appropriate.
1326 */ 1341 */
1327 _ReferenceInfo(this.enclosing, this.name, this.element, DartType specialType, 1342 _ReferenceInfo(this.libraryResynthesizer, this.enclosing, this.name,
1328 this.numTypeParameters) { 1343 this.element, DartType specialType, this.numTypeParameters) {
1329 if (specialType != null) { 1344 if (specialType != null) {
1330 type = specialType; 1345 type = specialType;
1331 } else { 1346 } else {
1332 type = _buildType((_) => DynamicTypeImpl.instance, const []); 1347 type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
1333 } 1348 }
1334 } 1349 }
1335 1350
1336 /** 1351 /**
1337 * Build a [DartType] corresponding to the result of applying some type 1352 * Build a [DartType] corresponding to the result of applying some type
1338 * arguments to the entity referred to by this [_ReferenceInfo]. The type 1353 * arguments to the entity referred to by this [_ReferenceInfo]. The type
1339 * arguments are retrieved by calling [getTypeArgument]. 1354 * arguments are retrieved by calling [getTypeArgument].
1340 * 1355 *
1341 * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be 1356 * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
1342 * created which refers to a function type implicitly defined by one of the 1357 * created which refers to a function type implicitly defined by one of the
1343 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in 1358 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
1344 * [EntityRef.implicitFunctionTypeIndices]. 1359 * [EntityRef.implicitFunctionTypeIndices].
1345 * 1360 *
1346 * If the entity referred to by this [_ReferenceInfo] is not a type, `null` 1361 * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
1347 * is returned. 1362 * is returned.
1348 */ 1363 */
1349 DartType buildType( 1364 DartType buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
1350 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) { 1365 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
1351 DartType result = 1366 DartType result =
1352 (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty) 1367 (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
1353 ? type 1368 ? type
1354 : _buildType(getTypeArgument, implicitFunctionTypeIndices); 1369 : _buildType(instantiateToBoundsAllowed, numTypeArguments,
1370 getTypeArgument, implicitFunctionTypeIndices);
1355 if (result == null) { 1371 if (result == null) {
1356 // TODO(paulberry): figure out how to handle this case (which should 1372 // TODO(paulberry): figure out how to handle this case (which should
1357 // only occur in the event of erroneous code). 1373 // only occur in the event of erroneous code).
1358 throw new UnimplementedError(); 1374 throw new UnimplementedError();
1359 } 1375 }
1360 return result; 1376 return result;
1361 } 1377 }
1362 1378
1363 /** 1379 /**
1364 * If this reference refers to a type, build a [DartType] which instantiates 1380 * If this reference refers to a type, build a [DartType]. Otherwise return
1365 * it with type arguments returned by [getTypeArgument]. Otherwise return 1381 * `null`. If [numTypeArguments] is the same as the [numTypeParameters],
1366 * `null`. 1382 * the type in instantiated with type arguments returned by [getTypeArgument],
1383 * otherwise it is instantiated with type parameter bounds (if strong mode),
1384 * or with `dynamic` type arguments.
1367 * 1385 *
1368 * If [implicitFunctionTypeIndices] is not null, a [DartType] should be 1386 * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
1369 * created which refers to a function type implicitly defined by one of the 1387 * created which refers to a function type implicitly defined by one of the
1370 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in 1388 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
1371 * [EntityRef.implicitFunctionTypeIndices]. 1389 * [EntityRef.implicitFunctionTypeIndices].
1372 */ 1390 */
1373 DartType _buildType( 1391 DartType _buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
1374 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) { 1392 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
1375 ElementHandle element = this.element; // To allow type promotion 1393 ElementHandle element = this.element; // To allow type promotion
1376 if (element is ClassElementHandle) { 1394 if (element is ClassElementHandle) {
1377 return new InterfaceTypeImpl.elementWithNameAndArgs(element, name, 1395 List<DartType> typeArguments = null;
1378 _buildTypeArguments(numTypeParameters, getTypeArgument)); 1396 // If type arguments are specified, use them.
1397 // Otherwise, delay until they are requested.
1398 if (numTypeParameters == 0) {
1399 typeArguments = const <DartType>[];
1400 } else if (numTypeArguments == numTypeParameters) {
1401 typeArguments = new List<DartType>(numTypeParameters);
1402 for (int i = 0; i < numTypeParameters; i++) {
1403 typeArguments[i] = getTypeArgument(i);
1404 }
1405 }
1406 InterfaceTypeImpl type =
1407 new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
1408 if (typeArguments == null) {
1409 typeArguments = element.typeParameters.map((typeParameter) {
1410 DartType bound = typeParameter.bound;
1411 return libraryResynthesizer.summaryResynthesizer.strongMode &&
1412 instantiateToBoundsAllowed &&
1413 bound != null ? bound : DynamicTypeImpl.instance;
1414 }).toList();
1415 }
1416 return typeArguments;
1417 });
1418 // Mark the type as having implicit type arguments, so that we don't
1419 // attempt to request them during constant expression resynthesizing.
1420 if (typeArguments == null) {
1421 libraryResynthesizer.typesWithImplicitTypeArguments.add(type);
1422 }
1423 // Done.
1424 return type;
1379 } else if (element is FunctionTypedElement) { 1425 } else if (element is FunctionTypedElement) {
1380 int numTypeArguments; 1426 int numTypeArguments;
1381 FunctionTypedElementComputer computer; 1427 FunctionTypedElementComputer computer;
1382 if (implicitFunctionTypeIndices.isNotEmpty) { 1428 if (implicitFunctionTypeIndices.isNotEmpty) {
1383 numTypeArguments = numTypeParameters; 1429 numTypeArguments = numTypeParameters;
1384 computer = () { 1430 computer = () {
1385 FunctionTypedElement element = this.element; 1431 FunctionTypedElement element = this.element;
1386 for (int index in implicitFunctionTypeIndices) { 1432 for (int index in implicitFunctionTypeIndices) {
1387 element = element.parameters[index].type.element; 1433 element = element.parameters[index].type.element;
1388 } 1434 }
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 element.propagatedType = 2251 element.propagatedType =
2206 buildLinkedType(serializedVariable.propagatedTypeSlot); 2252 buildLinkedType(serializedVariable.propagatedTypeSlot);
2207 } 2253 }
2208 2254
2209 /** 2255 /**
2210 * Build a [DartType] object based on a [EntityRef]. This [DartType] 2256 * Build a [DartType] object based on a [EntityRef]. This [DartType]
2211 * may refer to elements in other libraries than the library being 2257 * may refer to elements in other libraries than the library being
2212 * deserialized, so handles are used to avoid having to deserialize other 2258 * deserialized, so handles are used to avoid having to deserialize other
2213 * libraries in the process. 2259 * libraries in the process.
2214 */ 2260 */
2215 DartType buildType(EntityRef type, {bool defaultVoid: false}) { 2261 DartType buildType(EntityRef type,
2262 {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
2216 if (type == null) { 2263 if (type == null) {
2217 if (defaultVoid) { 2264 if (defaultVoid) {
2218 return VoidTypeImpl.instance; 2265 return VoidTypeImpl.instance;
2219 } else { 2266 } else {
2220 return DynamicTypeImpl.instance; 2267 return DynamicTypeImpl.instance;
2221 } 2268 }
2222 } 2269 }
2223 if (type.paramReference != 0) { 2270 if (type.paramReference != 0) {
2224 return getTypeParameterFromScope(type.paramReference); 2271 return getTypeParameterFromScope(type.paramReference);
2225 } else if (type.syntheticReturnType != null) { 2272 } else if (type.syntheticReturnType != null) {
(...skipping 10 matching lines...) Expand all
2236 } else { 2283 } else {
2237 DartType getTypeArgument(int i) { 2284 DartType getTypeArgument(int i) {
2238 if (i < type.typeArguments.length) { 2285 if (i < type.typeArguments.length) {
2239 return buildType(type.typeArguments[i]); 2286 return buildType(type.typeArguments[i]);
2240 } else { 2287 } else {
2241 return DynamicTypeImpl.instance; 2288 return DynamicTypeImpl.instance;
2242 } 2289 }
2243 } 2290 }
2244 _ReferenceInfo referenceInfo = referenceInfos[type.reference]; 2291 _ReferenceInfo referenceInfo = referenceInfos[type.reference];
2245 return referenceInfo.buildType( 2292 return referenceInfo.buildType(
2246 getTypeArgument, type.implicitFunctionTypeIndices); 2293 instantiateToBoundsAllowed,
2294 type.typeArguments.length,
2295 getTypeArgument,
2296 type.implicitFunctionTypeIndices);
2247 } 2297 }
2248 } 2298 }
2249 2299
2250 /** 2300 /**
2251 * Resynthesize a [FunctionTypeAliasElement] and place it in the 2301 * Resynthesize a [FunctionTypeAliasElement] and place it in the
2252 * [unitHolder]. 2302 * [unitHolder].
2253 */ 2303 */
2254 void buildTypedef(UnlinkedTypedef serializedTypedef) { 2304 void buildTypedef(UnlinkedTypedef serializedTypedef) {
2255 FunctionTypeAliasElementImpl functionTypeAliasElement = 2305 FunctionTypeAliasElementImpl functionTypeAliasElement =
2256 new FunctionTypeAliasElementImpl( 2306 new FunctionTypeAliasElementImpl(
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 initializerElement.setCodeRange(null, null); 2431 initializerElement.setCodeRange(null, null);
2382 variable.initializer = initializerElement; 2432 variable.initializer = initializerElement;
2383 } 2433 }
2384 2434
2385 /** 2435 /**
2386 * Finish creating a [TypeParameterElement] by deserializing its bound. 2436 * Finish creating a [TypeParameterElement] by deserializing its bound.
2387 */ 2437 */
2388 void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter, 2438 void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter,
2389 TypeParameterElementImpl typeParameterElement) { 2439 TypeParameterElementImpl typeParameterElement) {
2390 if (serializedTypeParameter.bound != null) { 2440 if (serializedTypeParameter.bound != null) {
2391 typeParameterElement.bound = buildType(serializedTypeParameter.bound); 2441 typeParameterElement.bound = buildType(serializedTypeParameter.bound,
2442 instantiateToBoundsAllowed: false);
2392 } 2443 }
2393 } 2444 }
2394 2445
2395 /** 2446 /**
2396 * Return a list of type arguments corresponding to [currentTypeParameters], 2447 * Return a list of type arguments corresponding to [currentTypeParameters],
2397 * skipping the innermost [skipLevels] nesting levels. 2448 * skipping the innermost [skipLevels] nesting levels.
2398 * 2449 *
2399 * Type parameters are listed in nesting order from innermost to outermost, 2450 * Type parameters are listed in nesting order from innermost to outermost,
2400 * and then in declaration order. So for instance if we are resynthesizing a 2451 * and then in declaration order. So for instance if we are resynthesizing a
2401 * method declared as `class C<T, U> { void m<V, W>() { ... } }`, then the 2452 * method declared as `class C<T, U> { void m<V, W>() { ... } }`, then the
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2533 } else { 2584 } else {
2534 throw new StateError('Unexpected element enclosing function:' 2585 throw new StateError('Unexpected element enclosing function:'
2535 ' ${enclosingElement.runtimeType}'); 2586 ' ${enclosingElement.runtimeType}');
2536 } 2587 }
2537 break; 2588 break;
2538 case ReferenceKind.prefix: 2589 case ReferenceKind.prefix:
2539 case ReferenceKind.unresolved: 2590 case ReferenceKind.unresolved:
2540 break; 2591 break;
2541 } 2592 }
2542 } 2593 }
2543 referenceInfos[i] = new _ReferenceInfo( 2594 referenceInfos[i] = new _ReferenceInfo(libraryResynthesizer,
2544 enclosingInfo, name, element, type, numTypeParameters); 2595 enclosingInfo, name, element, type, numTypeParameters);
2545 } 2596 }
2546 } 2597 }
2547 2598
2548 /** 2599 /**
2549 * Populate a [CompilationUnitElement] by deserializing all the elements 2600 * Populate a [CompilationUnitElement] by deserializing all the elements
2550 * contained in it. 2601 * contained in it.
2551 */ 2602 */
2552 void populateUnit() { 2603 void populateUnit() {
2553 unlinkedUnit.classes.forEach(buildClass); 2604 unlinkedUnit.classes.forEach(buildClass);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2620 2671
2621 /** 2672 /**
2622 * Return the defining type for a [ConstructorElement] by applying 2673 * Return the defining type for a [ConstructorElement] by applying
2623 * [typeArgumentRefs] to the given linked [info]. 2674 * [typeArgumentRefs] to the given linked [info].
2624 */ 2675 */
2625 InterfaceType _createConstructorDefiningType( 2676 InterfaceType _createConstructorDefiningType(
2626 _ReferenceInfo info, List<EntityRef> typeArgumentRefs) { 2677 _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
2627 bool isClass = info.element is ClassElement; 2678 bool isClass = info.element is ClassElement;
2628 _ReferenceInfo classInfo = isClass ? info : info.enclosing; 2679 _ReferenceInfo classInfo = isClass ? info : info.enclosing;
2629 List<DartType> typeArguments = typeArgumentRefs.map(buildType).toList(); 2680 List<DartType> typeArguments = typeArgumentRefs.map(buildType).toList();
2630 return classInfo.buildType((i) { 2681 return classInfo.buildType(true, typeArguments.length, (i) {
2631 if (i < typeArguments.length) { 2682 if (i < typeArguments.length) {
2632 return typeArguments[i]; 2683 return typeArguments[i];
2633 } else { 2684 } else {
2634 return DynamicTypeImpl.instance; 2685 return DynamicTypeImpl.instance;
2635 } 2686 }
2636 }, const <int>[]); 2687 }, const <int>[]);
2637 } 2688 }
2638 2689
2639 /** 2690 /**
2640 * Return the [ConstructorElement] corresponding to the given linked [info], 2691 * Return the [ConstructorElement] corresponding to the given linked [info],
(...skipping 22 matching lines...) Expand all
2663 static String _getElementIdentifier(String name, ReferenceKind kind) { 2714 static String _getElementIdentifier(String name, ReferenceKind kind) {
2664 if (kind == ReferenceKind.topLevelPropertyAccessor || 2715 if (kind == ReferenceKind.topLevelPropertyAccessor ||
2665 kind == ReferenceKind.propertyAccessor) { 2716 kind == ReferenceKind.propertyAccessor) {
2666 if (!name.endsWith('=')) { 2717 if (!name.endsWith('=')) {
2667 return name + '?'; 2718 return name + '?';
2668 } 2719 }
2669 } 2720 }
2670 return name; 2721 return name;
2671 } 2722 }
2672 } 2723 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698