Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 serialization.summarize_ast; | 5 library serialization.summarize_ast; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/ast/visitor.dart'; | 9 import 'package:analyzer/dart/ast/visitor.dart'; |
| 10 import 'package:analyzer/dart/element/type.dart' show DartType; | 10 import 'package:analyzer/dart/element/type.dart' show DartType; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 } | 22 } |
| 23 | 23 |
| 24 /** | 24 /** |
| 25 * Instances of this class keep track of intermediate state during | 25 * Instances of this class keep track of intermediate state during |
| 26 * serialization of a single constant [Expression]. | 26 * serialization of a single constant [Expression]. |
| 27 */ | 27 */ |
| 28 class _ConstExprSerializer extends AbstractConstExprSerializer { | 28 class _ConstExprSerializer extends AbstractConstExprSerializer { |
| 29 final _SummarizeAstVisitor visitor; | 29 final _SummarizeAstVisitor visitor; |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * If the expression being serialized can contain closures, map whose | |
| 33 * keys are the offsets of local function nodes representing those closures, | |
| 34 * and whose values are indices of those local functions relative to their | |
| 35 * siblings. | |
| 36 */ | |
| 37 final Map<int, int> localClosureIndexMap; | |
| 38 | |
| 39 /** | |
| 32 * If a constructor initializer expression is being serialized, the names of | 40 * If a constructor initializer expression is being serialized, the names of |
| 33 * the constructor parameters. Otherwise `null`. | 41 * the constructor parameters. Otherwise `null`. |
| 34 */ | 42 */ |
| 35 final Set<String> constructorParameterNames; | 43 final Set<String> constructorParameterNames; |
| 36 | 44 |
| 37 _ConstExprSerializer(this.visitor, this.constructorParameterNames); | 45 _ConstExprSerializer( |
| 46 this.visitor, this.localClosureIndexMap, this.constructorParameterNames); | |
| 38 | 47 |
| 39 @override | 48 @override |
| 40 bool isConstructorParameterName(String name) { | 49 bool isConstructorParameterName(String name) { |
| 41 return constructorParameterNames?.contains(name) ?? false; | 50 return constructorParameterNames?.contains(name) ?? false; |
| 42 } | 51 } |
| 43 | 52 |
| 44 @override | 53 @override |
| 45 void serializeAnnotation(Annotation annotation) { | 54 void serializeAnnotation(Annotation annotation) { |
| 46 if (annotation.arguments == null) { | 55 if (annotation.arguments == null) { |
| 47 assert(annotation.constructorName == null); | 56 assert(annotation.constructorName == null); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 67 if (name == null) { | 76 if (name == null) { |
| 68 return typeBuilder; | 77 return typeBuilder; |
| 69 } else { | 78 } else { |
| 70 int nameRef = | 79 int nameRef = |
| 71 visitor.serializeReference(typeBuilder.reference, name.name); | 80 visitor.serializeReference(typeBuilder.reference, name.name); |
| 72 return new EntityRefBuilder( | 81 return new EntityRefBuilder( |
| 73 reference: nameRef, typeArguments: typeBuilder.typeArguments); | 82 reference: nameRef, typeArguments: typeBuilder.typeArguments); |
| 74 } | 83 } |
| 75 } | 84 } |
| 76 | 85 |
| 86 @override | |
| 87 List<int> serializeFunctionExpression(FunctionExpression functionExpression) { | |
| 88 int localIndex; | |
| 89 if (localClosureIndexMap == null) { | |
| 90 return null; | |
| 91 } else { | |
| 92 localIndex = localClosureIndexMap[functionExpression.offset]; | |
| 93 assert(localIndex != null); | |
| 94 return <int>[0, localIndex]; | |
| 95 } | |
| 96 } | |
| 97 | |
| 77 EntityRefBuilder serializeIdentifier(Identifier identifier) { | 98 EntityRefBuilder serializeIdentifier(Identifier identifier) { |
| 78 EntityRefBuilder b = new EntityRefBuilder(); | 99 EntityRefBuilder b = new EntityRefBuilder(); |
| 79 if (identifier is SimpleIdentifier) { | 100 if (identifier is SimpleIdentifier) { |
| 80 int index = visitor.serializeSimpleReference(identifier.name, | 101 int index = visitor.serializeSimpleReference(identifier.name, |
| 81 allowTypeParameter: true); | 102 allowTypeParameter: true); |
| 82 if (index < 0) { | 103 if (index < 0) { |
| 83 b.paramReference = -index; | 104 b.paramReference = -index; |
| 84 } else { | 105 } else { |
| 85 b.reference = index; | 106 b.reference = index; |
| 86 } | 107 } |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 * The number of slot ids which have been assigned to this compilation unit. | 331 * The number of slot ids which have been assigned to this compilation unit. |
| 311 */ | 332 */ |
| 312 int numSlots = 0; | 333 int numSlots = 0; |
| 313 | 334 |
| 314 /** | 335 /** |
| 315 * The [Block] that is being visited now, or `null` for non-local contexts. | 336 * The [Block] that is being visited now, or `null` for non-local contexts. |
| 316 */ | 337 */ |
| 317 Block enclosingBlock = null; | 338 Block enclosingBlock = null; |
| 318 | 339 |
| 319 /** | 340 /** |
| 341 * If an expression is being serialized which can contain closures, map whose | |
| 342 * keys are the offsets of local function nodes representing those closures, | |
| 343 * and whose values are indices of those local functions relative to their | |
| 344 * siblings. | |
| 345 */ | |
| 346 Map<int, int> _localClosureIndexMap; | |
| 347 | |
| 348 /** | |
| 320 * Create a slot id for storing a propagated or inferred type or const cycle | 349 * Create a slot id for storing a propagated or inferred type or const cycle |
| 321 * info. | 350 * info. |
| 322 */ | 351 */ |
| 323 int assignSlot() => ++numSlots; | 352 int assignSlot() => ++numSlots; |
| 324 | 353 |
| 325 /** | 354 /** |
| 326 * Build a [_Scope] object containing the names defined within the body of a | 355 * Build a [_Scope] object containing the names defined within the body of a |
| 327 * class declaration. | 356 * class declaration. |
| 328 */ | 357 */ |
| 329 _Scope buildClassMemberScope( | 358 _Scope buildClassMemberScope( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 352 /** | 381 /** |
| 353 * Serialize the given list of [annotations]. If there are no annotations, | 382 * Serialize the given list of [annotations]. If there are no annotations, |
| 354 * the empty list is returned. | 383 * the empty list is returned. |
| 355 */ | 384 */ |
| 356 List<UnlinkedConstBuilder> serializeAnnotations( | 385 List<UnlinkedConstBuilder> serializeAnnotations( |
| 357 NodeList<Annotation> annotations) { | 386 NodeList<Annotation> annotations) { |
| 358 if (annotations == null || annotations.isEmpty) { | 387 if (annotations == null || annotations.isEmpty) { |
| 359 return const <UnlinkedConstBuilder>[]; | 388 return const <UnlinkedConstBuilder>[]; |
| 360 } | 389 } |
| 361 return annotations.map((Annotation a) { | 390 return annotations.map((Annotation a) { |
| 362 _ConstExprSerializer serializer = new _ConstExprSerializer(this, null); | 391 var localClosureIndexMap = null; // TODO(paulberry): fix. |
|
scheglov
2016/05/10 21:47:03
Do we want to have types for these variables?
Paul Berry
2016/05/10 22:04:15
Good point. Fixed.
| |
| 392 _ConstExprSerializer serializer = | |
| 393 new _ConstExprSerializer(this, localClosureIndexMap, null); | |
| 363 serializer.serializeAnnotation(a); | 394 serializer.serializeAnnotation(a); |
| 364 return serializer.toBuilder(); | 395 return serializer.toBuilder(); |
| 365 }).toList(); | 396 }).toList(); |
| 366 } | 397 } |
| 367 | 398 |
| 368 /** | 399 /** |
| 369 * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass] | 400 * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass] |
| 370 * and store the result in [classes]. | 401 * and store the result in [classes]. |
| 371 */ | 402 */ |
| 372 void serializeClass( | 403 void serializeClass( |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 b.references = unlinkedReferences; | 511 b.references = unlinkedReferences; |
| 481 b.typedefs = typedefs; | 512 b.typedefs = typedefs; |
| 482 b.variables = variables; | 513 b.variables = variables; |
| 483 b.publicNamespace = computePublicNamespace(compilationUnit); | 514 b.publicNamespace = computePublicNamespace(compilationUnit); |
| 484 return b; | 515 return b; |
| 485 } | 516 } |
| 486 | 517 |
| 487 /** | 518 /** |
| 488 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. | 519 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. |
| 489 */ | 520 */ |
| 490 UnlinkedConstBuilder serializeConstExpr(Expression expression, | 521 UnlinkedConstBuilder serializeConstExpr( |
| 522 Map<int, int> localClosureIndexMap, Expression expression, | |
| 491 [Set<String> constructorParameterNames]) { | 523 [Set<String> constructorParameterNames]) { |
| 492 _ConstExprSerializer serializer = | 524 _ConstExprSerializer serializer = new _ConstExprSerializer( |
| 493 new _ConstExprSerializer(this, constructorParameterNames); | 525 this, localClosureIndexMap, constructorParameterNames); |
| 494 serializer.serialize(expression); | 526 serializer.serialize(expression); |
| 495 return serializer.toBuilder(); | 527 return serializer.toBuilder(); |
| 496 } | 528 } |
| 497 | 529 |
| 498 /** | 530 /** |
| 499 * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and | 531 * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and |
| 500 * store it in [variables]. | 532 * store it in [variables]. |
| 501 */ | 533 */ |
| 502 void serializeDeclaredIdentifier( | 534 void serializeDeclaredIdentifier( |
| 503 AstNode scopeNode, | 535 AstNode scopeNode, |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); | 875 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); |
| 844 b.isFinal = variables.isFinal; | 876 b.isFinal = variables.isFinal; |
| 845 b.isConst = variables.isConst; | 877 b.isConst = variables.isConst; |
| 846 b.isStatic = isDeclaredStatic; | 878 b.isStatic = isDeclaredStatic; |
| 847 b.name = variable.name.name; | 879 b.name = variable.name.name; |
| 848 b.nameOffset = variable.name.offset; | 880 b.nameOffset = variable.name.offset; |
| 849 b.type = serializeTypeName(variables.type); | 881 b.type = serializeTypeName(variables.type); |
| 850 b.documentationComment = serializeDocumentation(documentationComment); | 882 b.documentationComment = serializeDocumentation(documentationComment); |
| 851 b.annotations = serializeAnnotations(annotations); | 883 b.annotations = serializeAnnotations(annotations); |
| 852 b.codeRange = serializeCodeRange(variables.parent); | 884 b.codeRange = serializeCodeRange(variables.parent); |
| 885 Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() { | |
| 886 b.initializer = serializeInitializerFunction(variable.initializer); | |
| 887 }); | |
| 853 if (variable.isConst || | 888 if (variable.isConst || |
| 854 variable.isFinal && isField && !isDeclaredStatic || | 889 variable.isFinal && isField && !isDeclaredStatic || |
| 855 variables.type == null) { | 890 variables.type == null) { |
| 856 Expression initializer = variable.initializer; | 891 Expression initializer = variable.initializer; |
| 857 if (initializer != null) { | 892 if (initializer != null) { |
| 858 b.constExpr = serializeConstExpr(initializer); | 893 b.constExpr = serializeConstExpr(localClosureIndexMap, initializer); |
| 859 } | 894 } |
| 860 } | 895 } |
| 861 if (variable.initializer != null && | 896 if (variable.initializer != null && |
| 862 (variables.isFinal || variables.isConst)) { | 897 (variables.isFinal || variables.isConst)) { |
| 863 b.propagatedTypeSlot = assignSlot(); | 898 b.propagatedTypeSlot = assignSlot(); |
| 864 } | 899 } |
| 865 bool isSemanticallyStatic = !isField || isDeclaredStatic; | 900 bool isSemanticallyStatic = !isField || isDeclaredStatic; |
| 866 if (variables.type == null && | 901 if (variables.type == null && |
| 867 (variable.initializer != null || !isSemanticallyStatic)) { | 902 (variable.initializer != null || !isSemanticallyStatic)) { |
| 868 b.inferredTypeSlot = assignSlot(); | 903 b.inferredTypeSlot = assignSlot(); |
| 869 } | 904 } |
| 870 b.visibleOffset = scopeNode?.offset; | 905 b.visibleOffset = scopeNode?.offset; |
| 871 b.visibleLength = scopeNode?.length; | 906 b.visibleLength = scopeNode?.length; |
| 872 b.initializer = serializeInitializerFunction(variable.initializer); | |
| 873 this.variables.add(b); | 907 this.variables.add(b); |
| 874 } | 908 } |
| 875 } | 909 } |
| 876 | 910 |
| 877 @override | 911 @override |
| 878 void visitBlock(Block node) { | 912 void visitBlock(Block node) { |
| 879 Block oldBlock = enclosingBlock; | 913 Block oldBlock = enclosingBlock; |
| 880 enclosingBlock = node; | 914 enclosingBlock = node; |
| 881 super.visitBlock(node); | 915 super.visitBlock(node); |
| 882 enclosingBlock = oldBlock; | 916 enclosingBlock = oldBlock; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 946 } | 980 } |
| 947 b.parameters = node.parameters.parameters | 981 b.parameters = node.parameters.parameters |
| 948 .map((FormalParameter p) => p.accept(this)) | 982 .map((FormalParameter p) => p.accept(this)) |
| 949 .toList(); | 983 .toList(); |
| 950 b.kind = UnlinkedExecutableKind.constructor; | 984 b.kind = UnlinkedExecutableKind.constructor; |
| 951 if (node.factoryKeyword != null) { | 985 if (node.factoryKeyword != null) { |
| 952 b.isFactory = true; | 986 b.isFactory = true; |
| 953 if (node.redirectedConstructor != null) { | 987 if (node.redirectedConstructor != null) { |
| 954 b.isRedirectedConstructor = true; | 988 b.isRedirectedConstructor = true; |
| 955 TypeName typeName = node.redirectedConstructor.type; | 989 TypeName typeName = node.redirectedConstructor.type; |
| 956 b.redirectedConstructor = new _ConstExprSerializer(this, null) | 990 var localClosureIndexMap = null; // TODO(paulberry): fix. |
| 957 .serializeConstructorRef(null, typeName.name, | 991 b.redirectedConstructor = |
| 958 typeName.typeArguments, node.redirectedConstructor.name); | 992 new _ConstExprSerializer(this, localClosureIndexMap, null) |
| 993 .serializeConstructorRef(null, typeName.name, | |
| 994 typeName.typeArguments, node.redirectedConstructor.name); | |
| 959 } | 995 } |
| 960 } else { | 996 } else { |
| 961 for (ConstructorInitializer initializer in node.initializers) { | 997 for (ConstructorInitializer initializer in node.initializers) { |
| 962 if (initializer is RedirectingConstructorInvocation) { | 998 if (initializer is RedirectingConstructorInvocation) { |
| 963 b.isRedirectedConstructor = true; | 999 b.isRedirectedConstructor = true; |
| 964 b.redirectedConstructorName = initializer.constructorName?.name; | 1000 b.redirectedConstructorName = initializer.constructorName?.name; |
| 965 } | 1001 } |
| 966 } | 1002 } |
| 967 } | 1003 } |
| 968 if (node.constKeyword != null) { | 1004 if (node.constKeyword != null) { |
| 969 b.isConst = true; | 1005 b.isConst = true; |
| 970 b.constCycleSlot = assignSlot(); | 1006 b.constCycleSlot = assignSlot(); |
| 971 } | 1007 } |
| 972 b.isExternal = node.externalKeyword != null; | 1008 b.isExternal = node.externalKeyword != null; |
| 973 b.documentationComment = serializeDocumentation(node.documentationComment); | 1009 b.documentationComment = serializeDocumentation(node.documentationComment); |
| 974 b.annotations = serializeAnnotations(node.metadata); | 1010 b.annotations = serializeAnnotations(node.metadata); |
| 975 b.codeRange = serializeCodeRange(node); | 1011 b.codeRange = serializeCodeRange(node); |
| 976 if (node.constKeyword != null) { | 1012 if (node.constKeyword != null) { |
| 977 Set<String> constructorParameterNames = | 1013 Set<String> constructorParameterNames = |
| 978 node.parameters.parameters.map((p) => p.identifier.name).toSet(); | 1014 node.parameters.parameters.map((p) => p.identifier.name).toSet(); |
| 1015 var localClosureIndexMap = null; // TODO(paulberry): fix. | |
| 979 b.constantInitializers = node.initializers | 1016 b.constantInitializers = node.initializers |
| 980 .map((ConstructorInitializer initializer) => | 1017 .map((ConstructorInitializer initializer) => |
| 981 serializeConstructorInitializer(initializer, (Expression expr) { | 1018 serializeConstructorInitializer(initializer, (Expression expr) { |
| 982 return serializeConstExpr(expr, constructorParameterNames); | 1019 return serializeConstExpr( |
| 1020 localClosureIndexMap, expr, constructorParameterNames); | |
| 983 })) | 1021 })) |
| 984 .toList(); | 1022 .toList(); |
| 985 } | 1023 } |
| 986 serializeFunctionBody(b, node.body); | 1024 serializeFunctionBody(b, node.body); |
| 987 executables.add(b); | 1025 executables.add(b); |
| 988 } | 1026 } |
| 989 | 1027 |
| 990 @override | 1028 @override |
| 991 UnlinkedParamBuilder visitDefaultFormalParameter( | 1029 UnlinkedParamBuilder visitDefaultFormalParameter( |
| 992 DefaultFormalParameter node) { | 1030 DefaultFormalParameter node) { |
| 993 UnlinkedParamBuilder b = node.parameter.accept(this); | 1031 UnlinkedParamBuilder b = node.parameter.accept(this); |
| 994 if (node.defaultValue != null) { | 1032 if (node.defaultValue != null) { |
| 995 b.defaultValue = serializeConstExpr(node.defaultValue); | 1033 var localClosureIndexMap = null; // TODO(paulberry): fix. |
| 1034 b.defaultValue = | |
| 1035 serializeConstExpr(localClosureIndexMap, node.defaultValue); | |
| 996 b.defaultValueCode = node.defaultValue.toSource(); | 1036 b.defaultValueCode = node.defaultValue.toSource(); |
| 997 } | 1037 } |
| 998 b.initializer = serializeInitializerFunction(node.defaultValue); | 1038 b.initializer = serializeInitializerFunction(node.defaultValue); |
| 999 b.codeRange = serializeCodeRange(node); | 1039 b.codeRange = serializeCodeRange(node); |
| 1000 return b; | 1040 return b; |
| 1001 } | 1041 } |
| 1002 | 1042 |
| 1003 @override | 1043 @override |
| 1004 void visitEnumDeclaration(EnumDeclaration node) { | 1044 void visitEnumDeclaration(EnumDeclaration node) { |
| 1005 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); | 1045 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1088 false, | 1128 false, |
| 1089 node.documentationComment, | 1129 node.documentationComment, |
| 1090 node.metadata, | 1130 node.metadata, |
| 1091 node.functionExpression.typeParameters, | 1131 node.functionExpression.typeParameters, |
| 1092 node.externalKeyword != null)); | 1132 node.externalKeyword != null)); |
| 1093 } | 1133 } |
| 1094 | 1134 |
| 1095 @override | 1135 @override |
| 1096 void visitFunctionExpression(FunctionExpression node) { | 1136 void visitFunctionExpression(FunctionExpression node) { |
| 1097 if (node.parent is! FunctionDeclaration) { | 1137 if (node.parent is! FunctionDeclaration) { |
| 1138 if (_localClosureIndexMap != null) { | |
| 1139 _localClosureIndexMap[node.offset] = executables.length; | |
| 1140 } | |
| 1098 executables.add(serializeExecutable( | 1141 executables.add(serializeExecutable( |
| 1099 node, | 1142 node, |
| 1100 null, | 1143 null, |
| 1101 node.offset, | 1144 node.offset, |
| 1102 false, | 1145 false, |
| 1103 false, | 1146 false, |
| 1104 null, | 1147 null, |
| 1105 node.parameters, | 1148 node.parameters, |
| 1106 node.body, | 1149 node.body, |
| 1107 false, | 1150 false, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1250 return b; | 1293 return b; |
| 1251 } | 1294 } |
| 1252 | 1295 |
| 1253 @override | 1296 @override |
| 1254 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { | 1297 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 1255 serializeVariables( | 1298 serializeVariables( |
| 1256 enclosingBlock, node.variables, false, null, null, false); | 1299 enclosingBlock, node.variables, false, null, null, false); |
| 1257 } | 1300 } |
| 1258 | 1301 |
| 1259 /** | 1302 /** |
| 1303 * Execute [callback], gathering any local closures in | |
| 1304 * [_localClosureIndexMap], and return the resulting map. | |
| 1305 * | |
| 1306 * Properly handles cases where one closure is nested within another. | |
| 1307 */ | |
| 1308 Map<int, int> _withLocalClosureIndexMap(void callback()) { | |
| 1309 Map<int, int> prevLocalClosureIndexMap = _localClosureIndexMap; | |
| 1310 _localClosureIndexMap = <int, int>{}; | |
| 1311 callback(); | |
| 1312 Map<int, int> localClosureIndexMap = _localClosureIndexMap; | |
| 1313 _localClosureIndexMap = prevLocalClosureIndexMap; | |
| 1314 return localClosureIndexMap; | |
| 1315 } | |
| 1316 | |
| 1317 /** | |
| 1260 * Helper method to determine if a given [typeName] refers to `dynamic`. | 1318 * Helper method to determine if a given [typeName] refers to `dynamic`. |
| 1261 */ | 1319 */ |
| 1262 static bool isDynamic(TypeName typeName) { | 1320 static bool isDynamic(TypeName typeName) { |
| 1263 Identifier name = typeName.name; | 1321 Identifier name = typeName.name; |
| 1264 return name is SimpleIdentifier && name.name == 'dynamic'; | 1322 return name is SimpleIdentifier && name.name == 'dynamic'; |
| 1265 } | 1323 } |
| 1266 } | 1324 } |
| 1267 | 1325 |
| 1268 /** | 1326 /** |
| 1269 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. | 1327 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. |
| 1270 */ | 1328 */ |
| 1271 class _TypeParameterScope extends _Scope { | 1329 class _TypeParameterScope extends _Scope { |
| 1272 /** | 1330 /** |
| 1273 * Get the number of [_ScopedTypeParameter]s defined in this | 1331 * Get the number of [_ScopedTypeParameter]s defined in this |
| 1274 * [_TypeParameterScope]. | 1332 * [_TypeParameterScope]. |
| 1275 */ | 1333 */ |
| 1276 int get length => _definedNames.length; | 1334 int get length => _definedNames.length; |
| 1277 } | 1335 } |
| OLD | NEW |