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 fasta.kernel_library_builder; | 5 library fasta.kernel_library_builder; |
| 6 | 6 |
| 7 import 'package:kernel/ast.dart'; | 7 import 'package:kernel/ast.dart'; |
| 8 | 8 |
| 9 import 'package:kernel/clone.dart' show CloneVisitor; | 9 import 'package:kernel/clone.dart' show CloneVisitor; |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 KernelFunctionTypeBuilder, | 39 KernelFunctionTypeBuilder, |
| 40 KernelInvalidTypeBuilder, | 40 KernelInvalidTypeBuilder, |
| 41 KernelMixinApplicationBuilder, | 41 KernelMixinApplicationBuilder, |
| 42 KernelNamedMixinApplicationBuilder, | 42 KernelNamedMixinApplicationBuilder, |
| 43 KernelNamedTypeBuilder, | 43 KernelNamedTypeBuilder, |
| 44 KernelProcedureBuilder, | 44 KernelProcedureBuilder, |
| 45 KernelTypeBuilder, | 45 KernelTypeBuilder, |
| 46 KernelTypeVariableBuilder, | 46 KernelTypeVariableBuilder, |
| 47 MemberBuilder, | 47 MemberBuilder, |
| 48 MetadataBuilder, | 48 MetadataBuilder, |
| 49 MixedAccessor, | |
| 50 NamedMixinApplicationBuilder, | 49 NamedMixinApplicationBuilder, |
| 51 PrefixBuilder, | 50 PrefixBuilder, |
| 52 ProcedureBuilder, | 51 ProcedureBuilder, |
| 52 Scope, | |
| 53 TypeBuilder, | 53 TypeBuilder, |
| 54 TypeVariableBuilder, | 54 TypeVariableBuilder, |
| 55 compareProcedures; | 55 compareProcedures; |
| 56 | 56 |
| 57 class KernelLibraryBuilder | 57 class KernelLibraryBuilder |
| 58 extends SourceLibraryBuilder<KernelTypeBuilder, Library> { | 58 extends SourceLibraryBuilder<KernelTypeBuilder, Library> { |
| 59 final Library library; | 59 final Library library; |
| 60 | 60 |
| 61 final Map<String, SourceClassBuilder> mixinApplicationClasses = | 61 final Map<String, SourceClassBuilder> mixinApplicationClasses = |
| 62 <String, SourceClassBuilder>{}; | 62 <String, SourceClassBuilder>{}; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 void addClass( | 96 void addClass( |
| 97 List<MetadataBuilder> metadata, | 97 List<MetadataBuilder> metadata, |
| 98 int modifiers, | 98 int modifiers, |
| 99 String className, | 99 String className, |
| 100 List<TypeVariableBuilder> typeVariables, | 100 List<TypeVariableBuilder> typeVariables, |
| 101 KernelTypeBuilder supertype, | 101 KernelTypeBuilder supertype, |
| 102 List<KernelTypeBuilder> interfaces, | 102 List<KernelTypeBuilder> interfaces, |
| 103 int charOffset) { | 103 int charOffset) { |
| 104 assert(currentDeclaration.parent == libraryDeclaration); | 104 assert(currentDeclaration.parent == libraryDeclaration); |
| 105 Map<String, MemberBuilder> members = currentDeclaration.members; | 105 Map<String, MemberBuilder> members = currentDeclaration.members; |
| 106 Map<String, MemberBuilder> constructors = currentDeclaration.constructors; | |
| 107 Map<String, MemberBuilder> setters = currentDeclaration.setters; | |
| 108 | |
| 109 Scope classScope = new Scope( | |
| 110 members, setters, scope.withTypeVariables(typeVariables), | |
| 111 isModifiable: false); | |
| 112 | |
| 113 // When looking up a constructor, we don't consider type variables or the | |
| 114 // library scope. | |
| 115 Scope constructorScope = | |
| 116 new Scope(constructors, null, null, isModifiable: false); | |
| 106 ClassBuilder cls = new SourceClassBuilder( | 117 ClassBuilder cls = new SourceClassBuilder( |
| 107 metadata, | 118 metadata, |
| 108 modifiers, | 119 modifiers, |
| 109 className, | 120 className, |
| 110 typeVariables, | 121 typeVariables, |
| 111 supertype, | 122 supertype, |
| 112 interfaces, | 123 interfaces, |
| 113 members, | 124 classScope, |
| 125 constructorScope, | |
| 114 this, | 126 this, |
| 115 new List<ConstructorReferenceBuilder>.from(constructorReferences), | 127 new List<ConstructorReferenceBuilder>.from(constructorReferences), |
| 116 charOffset); | 128 charOffset); |
| 117 constructorReferences.clear(); | 129 constructorReferences.clear(); |
| 118 members.forEach((String name, MemberBuilder builder) { | 130 void setParent(String name, MemberBuilder member) { |
| 119 while (builder != null) { | 131 while (member != null) { |
| 120 builder.parent = cls; | 132 member.parent = cls; |
| 121 builder = builder.next; | 133 member = member.next; |
| 122 } | 134 } |
| 123 }); | 135 } |
| 136 | |
| 137 members.forEach(setParent); | |
| 138 constructors.forEach(setParent); | |
| 139 setters.forEach(setParent); | |
| 124 // Nested declaration began in `OutlineBuilder.beginClassDeclaration`. | 140 // Nested declaration began in `OutlineBuilder.beginClassDeclaration`. |
| 125 endNestedDeclaration().resolveTypes(typeVariables, this); | 141 endNestedDeclaration().resolveTypes(typeVariables, this); |
| 126 addBuilder(className, cls, charOffset); | 142 addBuilder(className, cls, charOffset); |
| 127 } | 143 } |
| 128 | 144 |
| 129 void addNamedMixinApplication( | 145 void addNamedMixinApplication( |
| 130 List<MetadataBuilder> metadata, | 146 List<MetadataBuilder> metadata, |
| 131 String name, | 147 String name, |
| 132 List<TypeVariableBuilder> typeVariables, | 148 List<TypeVariableBuilder> typeVariables, |
| 133 int modifiers, | 149 int modifiers, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 144 | 160 |
| 145 void addField(List<MetadataBuilder> metadata, int modifiers, | 161 void addField(List<MetadataBuilder> metadata, int modifiers, |
| 146 KernelTypeBuilder type, String name, int charOffset) { | 162 KernelTypeBuilder type, String name, int charOffset) { |
| 147 addBuilder( | 163 addBuilder( |
| 148 name, | 164 name, |
| 149 new KernelFieldBuilder( | 165 new KernelFieldBuilder( |
| 150 metadata, type, name, modifiers, this, charOffset), | 166 metadata, type, name, modifiers, this, charOffset), |
| 151 charOffset); | 167 charOffset); |
| 152 } | 168 } |
| 153 | 169 |
| 154 String computeConstructorName(String name) { | 170 String computeAndValidateConstructorName(String name, int charOffset) { |
| 155 assert(isConstructorName(name, currentDeclaration.name)); | 171 String className = currentDeclaration.name; |
| 172 bool startsWithClassName = name.startsWith(className); | |
| 173 if (startsWithClassName && name.length == className.length) { | |
| 174 // Unnamed constructor or factory. | |
| 175 return ""; | |
| 176 } | |
| 156 int index = name.indexOf("."); | 177 int index = name.indexOf("."); |
| 157 return index == -1 ? "" : name.substring(index + 1); | 178 if (startsWithClassName && index == className.length) { |
| 179 // Named constructor or factory. | |
| 180 return name.substring(index + 1); | |
| 181 } | |
| 182 if (index == -1) { | |
| 183 // A legal name. | |
|
karlklose
2017/04/03 08:05:37
How about 'A legal name for a method, but not for
ahe
2017/04/04 09:54:51
Done.
| |
| 184 return null; | |
| 185 } | |
| 186 String suffix = name.substring(index + 1); | |
| 187 addCompileTimeError( | |
| 188 charOffset, | |
| 189 "'$name' isn't a legal method name.\n" | |
| 190 "Did you mean '$className.$suffix'?"); | |
| 191 return suffix; | |
| 158 } | 192 } |
| 159 | 193 |
| 160 void addProcedure( | 194 void addProcedure( |
| 161 List<MetadataBuilder> metadata, | 195 List<MetadataBuilder> metadata, |
| 162 int modifiers, | 196 int modifiers, |
| 163 KernelTypeBuilder returnType, | 197 KernelTypeBuilder returnType, |
| 164 String name, | 198 String name, |
| 165 List<TypeVariableBuilder> typeVariables, | 199 List<TypeVariableBuilder> typeVariables, |
| 166 List<FormalParameterBuilder> formals, | 200 List<FormalParameterBuilder> formals, |
| 167 AsyncMarker asyncModifier, | 201 AsyncMarker asyncModifier, |
| 168 ProcedureKind kind, | 202 ProcedureKind kind, |
| 169 int charOffset, | 203 int charOffset, |
| 170 int charOpenParenOffset, | 204 int charOpenParenOffset, |
| 171 int charEndOffset, | 205 int charEndOffset, |
| 172 String nativeMethodName, | 206 String nativeMethodName, |
| 173 {bool isTopLevel}) { | 207 {bool isTopLevel}) { |
| 174 // Nested declaration began in `OutlineBuilder.beginMethod` or | 208 // Nested declaration began in `OutlineBuilder.beginMethod` or |
| 175 // `OutlineBuilder.beginTopLevelMethod`. | 209 // `OutlineBuilder.beginTopLevelMethod`. |
| 176 endNestedDeclaration().resolveTypes(typeVariables, this); | 210 endNestedDeclaration().resolveTypes(typeVariables, this); |
| 177 ProcedureBuilder procedure; | 211 ProcedureBuilder procedure; |
| 178 if (!isTopLevel && isConstructorName(name, currentDeclaration.name)) { | 212 String constructorName = |
| 179 name = computeConstructorName(name); | 213 isTopLevel ? null : computeAndValidateConstructorName(name, charOffset); |
| 214 if (constructorName != null) { | |
| 215 name = constructorName; | |
| 180 procedure = new KernelConstructorBuilder( | 216 procedure = new KernelConstructorBuilder( |
| 181 metadata, | 217 metadata, |
| 182 modifiers & ~abstractMask, | 218 modifiers & ~abstractMask, |
| 183 returnType, | 219 returnType, |
| 184 name, | 220 name, |
| 185 typeVariables, | 221 typeVariables, |
| 186 formals, | 222 formals, |
| 187 this, | 223 this, |
| 188 charOffset, | 224 charOffset, |
| 189 charOpenParenOffset, | 225 charOpenParenOffset, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 207 } | 243 } |
| 208 addBuilder(name, procedure, charOffset); | 244 addBuilder(name, procedure, charOffset); |
| 209 if (nativeMethodName != null) { | 245 if (nativeMethodName != null) { |
| 210 addNativeMethod(procedure); | 246 addNativeMethod(procedure); |
| 211 } | 247 } |
| 212 } | 248 } |
| 213 | 249 |
| 214 void addFactoryMethod( | 250 void addFactoryMethod( |
| 215 List<MetadataBuilder> metadata, | 251 List<MetadataBuilder> metadata, |
| 216 int modifiers, | 252 int modifiers, |
| 217 ConstructorReferenceBuilder constructorName, | 253 ConstructorReferenceBuilder constructorNameReference, |
| 218 List<FormalParameterBuilder> formals, | 254 List<FormalParameterBuilder> formals, |
| 219 AsyncMarker asyncModifier, | 255 AsyncMarker asyncModifier, |
| 220 ConstructorReferenceBuilder redirectionTarget, | 256 ConstructorReferenceBuilder redirectionTarget, |
| 221 int charOffset, | 257 int charOffset, |
| 222 int charOpenParenOffset, | 258 int charOpenParenOffset, |
| 223 int charEndOffset, | 259 int charEndOffset, |
| 224 String nativeMethodName) { | 260 String nativeMethodName) { |
| 225 // Nested declaration began in `OutlineBuilder.beginFactoryMethod`. | 261 // Nested declaration began in `OutlineBuilder.beginFactoryMethod`. |
| 226 DeclarationBuilder<KernelTypeBuilder> factoryDeclaration = | 262 DeclarationBuilder<KernelTypeBuilder> factoryDeclaration = |
| 227 endNestedDeclaration(); | 263 endNestedDeclaration(); |
| 228 String name = constructorName.name; | 264 String name = constructorNameReference.name; |
| 229 if (isConstructorName(name, currentDeclaration.name)) { | 265 String constructorName = |
| 230 name = computeConstructorName(name); | 266 computeAndValidateConstructorName(name, charOffset); |
| 267 if (constructorName != null) { | |
| 268 name = constructorName; | |
| 231 } | 269 } |
| 232 assert(constructorName.suffix == null); | 270 assert(constructorNameReference.suffix == null); |
| 233 KernelProcedureBuilder procedure = new KernelProcedureBuilder( | 271 KernelProcedureBuilder procedure = new KernelProcedureBuilder( |
| 234 metadata, | 272 metadata, |
| 235 staticMask | modifiers, | 273 staticMask | modifiers, |
| 236 null, | 274 null, |
| 237 name, | 275 name, |
| 238 <TypeVariableBuilder>[], | 276 <TypeVariableBuilder>[], |
| 239 formals, | 277 formals, |
| 240 asyncModifier, | 278 asyncModifier, |
| 241 ProcedureKind.Factory, | 279 ProcedureKind.Factory, |
| 242 this, | 280 this, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 super.build(); | 366 super.build(); |
| 329 library.name = name; | 367 library.name = name; |
| 330 library.procedures.sort(compareProcedures); | 368 library.procedures.sort(compareProcedures); |
| 331 return library; | 369 return library; |
| 332 } | 370 } |
| 333 | 371 |
| 334 @override | 372 @override |
| 335 Builder buildAmbiguousBuilder( | 373 Builder buildAmbiguousBuilder( |
| 336 String name, Builder builder, Builder other, int charOffset, | 374 String name, Builder builder, Builder other, int charOffset, |
| 337 {bool isExport: false, bool isImport: false}) { | 375 {bool isExport: false, bool isImport: false}) { |
| 376 // TODO(ahe): Can I move this to Scope or Prefix? | |
| 338 if (builder == other) return builder; | 377 if (builder == other) return builder; |
| 339 if (builder is InvalidTypeBuilder) return builder; | 378 if (builder is InvalidTypeBuilder) return builder; |
| 340 if (other is InvalidTypeBuilder) return other; | 379 if (other is InvalidTypeBuilder) return other; |
| 341 if (builder is AccessErrorBuilder) { | 380 if (builder is AccessErrorBuilder) { |
| 342 AccessErrorBuilder error = builder; | 381 AccessErrorBuilder error = builder; |
| 343 builder = error.builder; | 382 builder = error.builder; |
| 344 } | 383 } |
| 345 if (other is AccessErrorBuilder) { | 384 if (other is AccessErrorBuilder) { |
| 346 AccessErrorBuilder error = other; | 385 AccessErrorBuilder error = other; |
| 347 other = error.builder; | 386 other = error.builder; |
| 348 } | 387 } |
| 349 bool isLocal = false; | 388 bool isLocal = false; |
| 350 Builder preferred; | 389 Builder preferred; |
| 351 Uri uri; | 390 Uri uri; |
| 352 Uri otherUri; | 391 Uri otherUri; |
| 353 Uri preferredUri; | 392 Uri preferredUri; |
| 354 Uri hiddenUri; | 393 Uri hiddenUri; |
| 355 if (members[name] == builder) { | 394 if (scope.local[name] == builder) { |
| 356 isLocal = true; | 395 isLocal = true; |
| 357 preferred = builder; | 396 preferred = builder; |
| 358 hiddenUri = other.computeLibraryUri(); | 397 hiddenUri = other.computeLibraryUri(); |
| 359 } else { | 398 } else { |
| 360 uri = builder.computeLibraryUri(); | 399 uri = builder.computeLibraryUri(); |
| 361 otherUri = other.computeLibraryUri(); | 400 otherUri = other.computeLibraryUri(); |
| 362 if (otherUri?.scheme == "dart" && uri?.scheme != "dart") { | 401 if (otherUri?.scheme == "dart" && uri?.scheme != "dart") { |
| 363 preferred = builder; | 402 preferred = builder; |
| 364 preferredUri = uri; | 403 preferredUri = uri; |
| 365 hiddenUri = otherUri; | 404 hiddenUri = otherUri; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 387 } else { | 426 } else { |
| 388 addNit( | 427 addNit( |
| 389 charOffset, | 428 charOffset, |
| 390 "Import of '$name' (from '${preferredUri}') hides import from " | 429 "Import of '$name' (from '${preferredUri}') hides import from " |
| 391 "'${hiddenUri}'."); | 430 "'${hiddenUri}'."); |
| 392 } | 431 } |
| 393 } | 432 } |
| 394 return preferred; | 433 return preferred; |
| 395 } | 434 } |
| 396 if (builder.next == null && other.next == null) { | 435 if (builder.next == null && other.next == null) { |
| 397 if (builder.isGetter && other.isSetter) { | |
| 398 return new MixedAccessor(builder, other, this); | |
| 399 } else if (builder.isSetter && other.isGetter) { | |
| 400 return new MixedAccessor(other, builder, this); | |
| 401 } | |
| 402 if (isImport && builder is PrefixBuilder && other is PrefixBuilder) { | 436 if (isImport && builder is PrefixBuilder && other is PrefixBuilder) { |
| 403 // Handles the case where the same prefix is used for different | 437 // Handles the case where the same prefix is used for different |
| 404 // imports. | 438 // imports. |
| 405 PrefixBuilder prefix = builder; | 439 return builder |
| 406 other.exports.forEach((String name, Builder member) { | 440 ..exports.merge(other.exports, |
| 407 Builder existing = exports[name]; | 441 (String name, Builder existing, Builder member) { |
| 408 if (existing != null) { | 442 return buildAmbiguousBuilder(name, existing, member, charOffset, |
| 409 if (existing != member) { | 443 isExport: isExport, isImport: isImport); |
| 410 member = buildAmbiguousBuilder(name, existing, member, charOffset, | 444 }); |
| 411 isExport: isExport, isImport: isImport); | |
| 412 } | |
| 413 } | |
| 414 prefix.exports[name] = member; | |
| 415 }); | |
| 416 return builder; | |
| 417 } | 445 } |
| 418 } | 446 } |
| 419 if (isExport) { | 447 if (isExport) { |
| 420 addNit(charOffset, | 448 addNit(charOffset, |
| 421 "'$name' is exported from both '${uri}' and '${otherUri}'."); | 449 "'$name' is exported from both '${uri}' and '${otherUri}'."); |
| 422 } else { | 450 } else { |
| 423 addNit(charOffset, | 451 addNit(charOffset, |
| 424 "'$name' is imported from both '${uri}' and '${otherUri}'."); | 452 "'$name' is imported from both '${uri}' and '${otherUri}'."); |
| 425 } | 453 } |
| 426 return new KernelInvalidTypeBuilder(name, charOffset, fileUri); | 454 return new KernelInvalidTypeBuilder(name, charOffset, fileUri); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 } | 536 } |
| 509 | 537 |
| 510 @override | 538 @override |
| 511 void includePart(covariant KernelLibraryBuilder part) { | 539 void includePart(covariant KernelLibraryBuilder part) { |
| 512 super.includePart(part); | 540 super.includePart(part); |
| 513 nativeMethods.addAll(part.nativeMethods); | 541 nativeMethods.addAll(part.nativeMethods); |
| 514 boundlessTypeVariables.addAll(part.boundlessTypeVariables); | 542 boundlessTypeVariables.addAll(part.boundlessTypeVariables); |
| 515 assert(mixinApplicationClasses.isEmpty); | 543 assert(mixinApplicationClasses.isEmpty); |
| 516 } | 544 } |
| 517 } | 545 } |
| 518 | |
| 519 bool isConstructorName(String name, String className) { | |
| 520 if (name.startsWith(className)) { | |
| 521 if (name.length == className.length) return true; | |
| 522 if (name.startsWith(".", className.length)) return true; | |
| 523 } | |
| 524 return false; | |
| 525 } | |
| OLD | NEW |