| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 codegen.protocol; | 5 library codegen.protocol; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 | 8 |
| 9 import 'package:html/dom.dart' as dom; | 9 import 'package:html/dom.dart' as dom; |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 const Map<String, String> specialElementFlags = const { | 29 const Map<String, String> specialElementFlags = const { |
| 30 'abstract': '0x01', | 30 'abstract': '0x01', |
| 31 'const': '0x02', | 31 'const': '0x02', |
| 32 'final': '0x04', | 32 'final': '0x04', |
| 33 'static': '0x08', | 33 'static': '0x08', |
| 34 'private': '0x10', | 34 'private': '0x10', |
| 35 'deprecated': '0x20' | 35 'deprecated': '0x20' |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 final GeneratedFile target = | 38 final GeneratedFile target = |
| 39 new GeneratedFile('../../lib/src/generated_protocol.dart', () { | 39 new GeneratedFile('../../lib/plugin/protocol/generated_protocol.dart', () { |
| 40 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); | 40 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); |
| 41 return visitor.collectCode(visitor.visitApi); | 41 return visitor.collectCode(visitor.visitApi); |
| 42 }); | 42 }); |
| 43 | 43 |
| 44 /** | 44 /** |
| 45 * Callback type used to represent arbitrary code generation. | 45 * Callback type used to represent arbitrary code generation. |
| 46 */ | 46 */ |
| 47 typedef void CodegenCallback(); | 47 typedef void CodegenCallback(); |
| 48 | 48 |
| 49 typedef String FromJsonSnippetCallback(String jsonPath, String json); | 49 typedef String FromJsonSnippetCallback(String jsonPath, String json); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 60 * the constructor will default the member to the empty list. | 60 * the constructor will default the member to the empty list. |
| 61 */ | 61 */ |
| 62 static const Map<String, List<String>> _optionalConstructorArguments = const { | 62 static const Map<String, List<String>> _optionalConstructorArguments = const { |
| 63 'AnalysisErrorFixes': const ['fixes'], | 63 'AnalysisErrorFixes': const ['fixes'], |
| 64 'SourceChange': const ['edits', 'linkedEditGroups'], | 64 'SourceChange': const ['edits', 'linkedEditGroups'], |
| 65 'SourceFileEdit': const ['edits'], | 65 'SourceFileEdit': const ['edits'], |
| 66 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'], | 66 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'], |
| 67 }; | 67 }; |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * The disclaimer added to the documentation comment for each of the classes |
| 71 * that are generated. |
| 72 */ |
| 73 static const String disclaimer = |
| 74 'Clients are not expected to subtype this class.'; |
| 75 |
| 76 /** |
| 70 * Visitor used to produce doc comments. | 77 * Visitor used to produce doc comments. |
| 71 */ | 78 */ |
| 72 final ToHtmlVisitor toHtmlVisitor; | 79 final ToHtmlVisitor toHtmlVisitor; |
| 73 | 80 |
| 74 /** | 81 /** |
| 75 * Types implied by the API. This includes types explicitly named in the | 82 * Types implied by the API. This includes types explicitly named in the |
| 76 * API as well as those implied by the definitions of requests, responses, | 83 * API as well as those implied by the definitions of requests, responses, |
| 77 * notifications, etc. | 84 * notifications, etc. |
| 78 */ | 85 */ |
| 79 final Map<String, ImpliedType> impliedTypes; | 86 final Map<String, ImpliedType> impliedTypes; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 93 TypeDecl resolvedType = resolveTypeReferenceChain(type); | 100 TypeDecl resolvedType = resolveTypeReferenceChain(type); |
| 94 if (resolvedType is TypeReference || | 101 if (resolvedType is TypeReference || |
| 95 resolvedType is TypeEnum || | 102 resolvedType is TypeEnum || |
| 96 resolvedType is TypeObject || | 103 resolvedType is TypeObject || |
| 97 resolvedType is TypeUnion) { | 104 resolvedType is TypeUnion) { |
| 98 return '$thisVar == $otherVar'; | 105 return '$thisVar == $otherVar'; |
| 99 } else if (resolvedType is TypeList) { | 106 } else if (resolvedType is TypeList) { |
| 100 String itemTypeName = dartType(resolvedType.itemType); | 107 String itemTypeName = dartType(resolvedType.itemType); |
| 101 String subComparison = compareEqualsCode(resolvedType.itemType, 'a', 'b'); | 108 String subComparison = compareEqualsCode(resolvedType.itemType, 'a', 'b'); |
| 102 String closure = '($itemTypeName a, $itemTypeName b) => $subComparison'; | 109 String closure = '($itemTypeName a, $itemTypeName b) => $subComparison'; |
| 103 return '_listEqual($thisVar, $otherVar, $closure)'; | 110 return 'listEqual($thisVar, $otherVar, $closure)'; |
| 104 } else if (resolvedType is TypeMap) { | 111 } else if (resolvedType is TypeMap) { |
| 105 String valueTypeName = dartType(resolvedType.valueType); | 112 String valueTypeName = dartType(resolvedType.valueType); |
| 106 String subComparison = | 113 String subComparison = |
| 107 compareEqualsCode(resolvedType.valueType, 'a', 'b'); | 114 compareEqualsCode(resolvedType.valueType, 'a', 'b'); |
| 108 String closure = '($valueTypeName a, $valueTypeName b) => $subComparison'; | 115 String closure = '($valueTypeName a, $valueTypeName b) => $subComparison'; |
| 109 return '_mapEqual($thisVar, $otherVar, $closure)'; | 116 return 'mapEqual($thisVar, $otherVar, $closure)'; |
| 110 } | 117 } |
| 111 throw new Exception( | 118 throw new Exception( |
| 112 "Don't know how to compare for equality: $resolvedType"); | 119 "Don't know how to compare for equality: $resolvedType"); |
| 113 } | 120 } |
| 114 | 121 |
| 115 /** | 122 /** |
| 116 * Translate each type implied by the API to a class. | 123 * Translate each type implied by the API to a class. |
| 117 */ | 124 */ |
| 118 void emitClasses() { | 125 void emitClasses() { |
| 119 for (ImpliedType impliedType in impliedTypes.values) { | 126 for (ImpliedType impliedType in impliedTypes.values) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 /** | 212 /** |
| 206 * Emit a class representing an data structure that doesn't exist in the | 213 * Emit a class representing an data structure that doesn't exist in the |
| 207 * protocol because it is empty (e.g. the "params" object for a request that | 214 * protocol because it is empty (e.g. the "params" object for a request that |
| 208 * doesn't have any parameters). | 215 * doesn't have any parameters). |
| 209 */ | 216 */ |
| 210 void emitEmptyObjectClass(String className, ImpliedType impliedType) { | 217 void emitEmptyObjectClass(String className, ImpliedType impliedType) { |
| 211 docComment(toHtmlVisitor.collectHtml(() { | 218 docComment(toHtmlVisitor.collectHtml(() { |
| 212 toHtmlVisitor.p(() { | 219 toHtmlVisitor.p(() { |
| 213 toHtmlVisitor.write(impliedType.humanReadableName); | 220 toHtmlVisitor.write(impliedType.humanReadableName); |
| 214 }); | 221 }); |
| 222 toHtmlVisitor.p(() { |
| 223 toHtmlVisitor.write(disclaimer); |
| 224 }); |
| 215 })); | 225 })); |
| 216 writeln('class $className {'); | 226 writeln('class $className {'); |
| 217 indent(() { | 227 indent(() { |
| 218 if (emitToRequestMember(impliedType)) { | 228 if (emitToRequestMember(impliedType)) { |
| 219 writeln(); | 229 writeln(); |
| 220 } | 230 } |
| 221 if (emitToResponseMember(impliedType)) { | 231 if (emitToResponseMember(impliedType)) { |
| 222 writeln(); | 232 writeln(); |
| 223 } | 233 } |
| 224 if (emitToNotificationMember(impliedType)) { | 234 if (emitToNotificationMember(impliedType)) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 235 * Emit a class to encapsulate an enum. | 245 * Emit a class to encapsulate an enum. |
| 236 */ | 246 */ |
| 237 void emitEnumClass(String className, TypeEnum type, ImpliedType impliedType) { | 247 void emitEnumClass(String className, TypeEnum type, ImpliedType impliedType) { |
| 238 docComment(toHtmlVisitor.collectHtml(() { | 248 docComment(toHtmlVisitor.collectHtml(() { |
| 239 toHtmlVisitor.p(() { | 249 toHtmlVisitor.p(() { |
| 240 toHtmlVisitor.write(impliedType.humanReadableName); | 250 toHtmlVisitor.write(impliedType.humanReadableName); |
| 241 }); | 251 }); |
| 242 if (impliedType.type != null) { | 252 if (impliedType.type != null) { |
| 243 toHtmlVisitor.showType(null, impliedType.type); | 253 toHtmlVisitor.showType(null, impliedType.type); |
| 244 } | 254 } |
| 255 toHtmlVisitor.p(() { |
| 256 toHtmlVisitor.write(disclaimer); |
| 257 }); |
| 245 })); | 258 })); |
| 246 writeln('class $className implements Enum {'); | 259 writeln('class $className implements Enum {'); |
| 247 indent(() { | 260 indent(() { |
| 248 if (emitSpecialStaticMembers(className)) { | 261 if (emitSpecialStaticMembers(className)) { |
| 249 writeln(); | 262 writeln(); |
| 250 } | 263 } |
| 251 for (TypeEnumValue value in type.values) { | 264 for (TypeEnumValue value in type.values) { |
| 252 docComment(toHtmlVisitor.collectHtml(() { | 265 docComment(toHtmlVisitor.collectHtml(() { |
| 253 toHtmlVisitor.translateHtml(value.html); | 266 toHtmlVisitor.translateHtml(value.html); |
| 254 })); | 267 })); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 */ | 372 */ |
| 360 void emitObjectClass( | 373 void emitObjectClass( |
| 361 String className, TypeObject type, ImpliedType impliedType) { | 374 String className, TypeObject type, ImpliedType impliedType) { |
| 362 docComment(toHtmlVisitor.collectHtml(() { | 375 docComment(toHtmlVisitor.collectHtml(() { |
| 363 toHtmlVisitor.p(() { | 376 toHtmlVisitor.p(() { |
| 364 toHtmlVisitor.write(impliedType.humanReadableName); | 377 toHtmlVisitor.write(impliedType.humanReadableName); |
| 365 }); | 378 }); |
| 366 if (impliedType.type != null) { | 379 if (impliedType.type != null) { |
| 367 toHtmlVisitor.showType(null, impliedType.type); | 380 toHtmlVisitor.showType(null, impliedType.type); |
| 368 } | 381 } |
| 382 toHtmlVisitor.p(() { |
| 383 toHtmlVisitor.write(disclaimer); |
| 384 }); |
| 369 })); | 385 })); |
| 370 write('class $className'); | 386 write('class $className'); |
| 371 if (impliedType.kind == 'refactoringFeedback') { | 387 if (impliedType.kind == 'refactoringFeedback') { |
| 372 write(' extends RefactoringFeedback'); | 388 write(' extends RefactoringFeedback'); |
| 373 } | 389 } |
| 374 if (impliedType.kind == 'refactoringOptions') { | 390 if (impliedType.kind == 'refactoringOptions') { |
| 375 write(' extends RefactoringOptions'); | 391 write(' extends RefactoringOptions'); |
| 376 } | 392 } |
| 377 writeln(' implements HasToJson {'); | 393 writeln(' implements HasToJson {'); |
| 378 indent(() { | 394 indent(() { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 * Emit the method for decoding an object from JSON. | 562 * Emit the method for decoding an object from JSON. |
| 547 */ | 563 */ |
| 548 void emitObjectFromJsonConstructor( | 564 void emitObjectFromJsonConstructor( |
| 549 String className, TypeObject type, ImpliedType impliedType) { | 565 String className, TypeObject type, ImpliedType impliedType) { |
| 550 String humanReadableNameString = | 566 String humanReadableNameString = |
| 551 literalString(impliedType.humanReadableName); | 567 literalString(impliedType.humanReadableName); |
| 552 if (className == 'RefactoringFeedback') { | 568 if (className == 'RefactoringFeedback') { |
| 553 writeln('factory RefactoringFeedback.fromJson(JsonDecoder jsonDecoder, ' | 569 writeln('factory RefactoringFeedback.fromJson(JsonDecoder jsonDecoder, ' |
| 554 'String jsonPath, Object json, Map responseJson) {'); | 570 'String jsonPath, Object json, Map responseJson) {'); |
| 555 indent(() { | 571 indent(() { |
| 556 writeln('return _refactoringFeedbackFromJson(jsonDecoder, jsonPath, ' | 572 writeln('return refactoringFeedbackFromJson(jsonDecoder, jsonPath, ' |
| 557 'json, responseJson);'); | 573 'json, responseJson);'); |
| 558 }); | 574 }); |
| 559 writeln('}'); | 575 writeln('}'); |
| 560 return; | 576 return; |
| 561 } | 577 } |
| 562 if (className == 'RefactoringOptions') { | 578 if (className == 'RefactoringOptions') { |
| 563 writeln('factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, ' | 579 writeln('factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, ' |
| 564 'String jsonPath, Object json, RefactoringKind kind) {'); | 580 'String jsonPath, Object json, RefactoringKind kind) {'); |
| 565 indent(() { | 581 indent(() { |
| 566 writeln('return _refactoringOptionsFromJson(jsonDecoder, jsonPath, ' | 582 writeln('return refactoringOptionsFromJson(jsonDecoder, jsonPath, ' |
| 567 'json, kind);'); | 583 'json, kind);'); |
| 568 }); | 584 }); |
| 569 writeln('}'); | 585 writeln('}'); |
| 570 return; | 586 return; |
| 571 } | 587 } |
| 572 writeln( | 588 writeln( |
| 573 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O
bject json) {'); | 589 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O
bject json) {'); |
| 574 indent(() { | 590 indent(() { |
| 575 writeln('if (json == null) {'); | 591 writeln('if (json == null) {'); |
| 576 indent(() { | 592 indent(() { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 writeln('return ${className.hashCode};'); | 661 writeln('return ${className.hashCode};'); |
| 646 } else { | 662 } else { |
| 647 writeln('int hash = 0;'); | 663 writeln('int hash = 0;'); |
| 648 for (TypeObjectField field in type.fields) { | 664 for (TypeObjectField field in type.fields) { |
| 649 String valueToCombine; | 665 String valueToCombine; |
| 650 if (field.value != null) { | 666 if (field.value != null) { |
| 651 valueToCombine = field.value.hashCode.toString(); | 667 valueToCombine = field.value.hashCode.toString(); |
| 652 } else { | 668 } else { |
| 653 valueToCombine = '${field.name}.hashCode'; | 669 valueToCombine = '${field.name}.hashCode'; |
| 654 } | 670 } |
| 655 writeln('hash = _JenkinsSmiHash.combine(hash, $valueToCombine);'); | 671 writeln('hash = JenkinsSmiHash.combine(hash, $valueToCombine);'); |
| 656 } | 672 } |
| 657 writeln('return _JenkinsSmiHash.finish(hash);'); | 673 writeln('return JenkinsSmiHash.finish(hash);'); |
| 658 } | 674 } |
| 659 }); | 675 }); |
| 660 writeln('}'); | 676 writeln('}'); |
| 661 } | 677 } |
| 662 | 678 |
| 663 /** | 679 /** |
| 664 * If the class named [className] requires special constructors, emit them | 680 * If the class named [className] requires special constructors, emit them |
| 665 * and return true. | 681 * and return true. |
| 666 */ | 682 */ |
| 667 bool emitSpecialConstructors(String className) { | 683 bool emitSpecialConstructors(String className) { |
| 668 switch (className) { | 684 switch (className) { |
| 669 case 'LinkedEditGroup': | 685 case 'LinkedEditGroup': |
| 670 docComment([new dom.Text('Construct an empty LinkedEditGroup.')]); | 686 docComment([new dom.Text('Construct an empty LinkedEditGroup.')]); |
| 671 writeln( | 687 writeln( |
| 672 'LinkedEditGroup.empty() : this(<Position>[], 0, <LinkedEditSuggesti
on>[]);'); | 688 'LinkedEditGroup.empty() : this(<Position>[], 0, <LinkedEditSuggesti
on>[]);'); |
| 673 return true; | 689 return true; |
| 674 case 'RefactoringProblemSeverity': | 690 case 'RefactoringProblemSeverity': |
| 675 docComment([ | 691 docComment([ |
| 676 new dom.Text( | 692 new dom.Text( |
| 677 'Returns the [RefactoringProblemSeverity] with the maximal severit
y.') | 693 'Returns the [RefactoringProblemSeverity] with the maximal severit
y.') |
| 678 ]); | 694 ]); |
| 679 writeln( | 695 writeln( |
| 680 'static RefactoringProblemSeverity max(RefactoringProblemSeverity a,
RefactoringProblemSeverity b) =>'); | 696 'static RefactoringProblemSeverity max(RefactoringProblemSeverity a,
RefactoringProblemSeverity b) =>'); |
| 681 writeln(' _maxRefactoringProblemSeverity(a, b);'); | 697 writeln(' maxRefactoringProblemSeverity(a, b);'); |
| 682 return true; | 698 return true; |
| 683 default: | 699 default: |
| 684 return false; | 700 return false; |
| 685 } | 701 } |
| 686 } | 702 } |
| 687 | 703 |
| 688 /** | 704 /** |
| 689 * If the class named [className] requires special getters, emit them and | 705 * If the class named [className] requires special getters, emit them and |
| 690 * return true. | 706 * return true. |
| 691 */ | 707 */ |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 indent(() { | 743 indent(() { |
| 728 writeln('suggestions.add(suggestion);'); | 744 writeln('suggestions.add(suggestion);'); |
| 729 }); | 745 }); |
| 730 writeln('}'); | 746 writeln('}'); |
| 731 return true; | 747 return true; |
| 732 case 'SourceChange': | 748 case 'SourceChange': |
| 733 docComment([ | 749 docComment([ |
| 734 new dom.Text('Adds [edit] to the [FileEdit] for the given [file].') | 750 new dom.Text('Adds [edit] to the [FileEdit] for the given [file].') |
| 735 ]); | 751 ]); |
| 736 writeln('void addEdit(String file, int fileStamp, SourceEdit edit) =>'); | 752 writeln('void addEdit(String file, int fileStamp, SourceEdit edit) =>'); |
| 737 writeln(' _addEditToSourceChange(this, file, fileStamp, edit);'); | 753 writeln(' addEditToSourceChange(this, file, fileStamp, edit);'); |
| 738 writeln(); | 754 writeln(); |
| 739 docComment([new dom.Text('Adds the given [FileEdit].')]); | 755 docComment([new dom.Text('Adds the given [FileEdit].')]); |
| 740 writeln('void addFileEdit(SourceFileEdit edit) {'); | 756 writeln('void addFileEdit(SourceFileEdit edit) {'); |
| 741 indent(() { | 757 indent(() { |
| 742 writeln('edits.add(edit);'); | 758 writeln('edits.add(edit);'); |
| 743 }); | 759 }); |
| 744 writeln('}'); | 760 writeln('}'); |
| 745 writeln(); | 761 writeln(); |
| 746 docComment([new dom.Text('Adds the given [LinkedEditGroup].')]); | 762 docComment([new dom.Text('Adds the given [LinkedEditGroup].')]); |
| 747 writeln('void addLinkedEditGroup(LinkedEditGroup linkedEditGroup) {'); | 763 writeln('void addLinkedEditGroup(LinkedEditGroup linkedEditGroup) {'); |
| 748 indent(() { | 764 indent(() { |
| 749 writeln('linkedEditGroups.add(linkedEditGroup);'); | 765 writeln('linkedEditGroups.add(linkedEditGroup);'); |
| 750 }); | 766 }); |
| 751 writeln('}'); | 767 writeln('}'); |
| 752 writeln(); | 768 writeln(); |
| 753 docComment([ | 769 docComment([ |
| 754 new dom.Text( | 770 new dom.Text( |
| 755 'Returns the [FileEdit] for the given [file], maybe `null`.') | 771 'Returns the [FileEdit] for the given [file], maybe `null`.') |
| 756 ]); | 772 ]); |
| 757 writeln('SourceFileEdit getFileEdit(String file) =>'); | 773 writeln('SourceFileEdit getFileEdit(String file) =>'); |
| 758 writeln(' _getChangeFileEdit(this, file);'); | 774 writeln(' getChangeFileEdit(this, file);'); |
| 759 return true; | 775 return true; |
| 760 case 'SourceEdit': | 776 case 'SourceEdit': |
| 761 docComment([ | 777 docComment([ |
| 762 new dom.Text( | 778 new dom.Text( |
| 763 'Get the result of applying the edit to the given [code].') | 779 'Get the result of applying the edit to the given [code].') |
| 764 ]); | 780 ]); |
| 765 writeln('String apply(String code) => _applyEdit(code, this);'); | 781 writeln('String apply(String code) => applyEdit(code, this);'); |
| 766 return true; | 782 return true; |
| 767 case 'SourceFileEdit': | 783 case 'SourceFileEdit': |
| 768 docComment([new dom.Text('Adds the given [Edit] to the list.')]); | 784 docComment([new dom.Text('Adds the given [Edit] to the list.')]); |
| 769 writeln('void add(SourceEdit edit) => _addEditForSource(this, edit);'); | 785 writeln('void add(SourceEdit edit) => addEditForSource(this, edit);'); |
| 770 writeln(); | 786 writeln(); |
| 771 docComment([new dom.Text('Adds the given [Edit]s.')]); | 787 docComment([new dom.Text('Adds the given [Edit]s.')]); |
| 772 writeln('void addAll(Iterable<SourceEdit> edits) =>'); | 788 writeln('void addAll(Iterable<SourceEdit> edits) =>'); |
| 773 writeln(' _addAllEditsForSource(this, edits);'); | 789 writeln(' addAllEditsForSource(this, edits);'); |
| 774 return true; | 790 return true; |
| 775 default: | 791 default: |
| 776 return false; | 792 return false; |
| 777 } | 793 } |
| 778 } | 794 } |
| 779 | 795 |
| 780 /** | 796 /** |
| 781 * If the class named [className] requires special static members, emit them | 797 * If the class named [className] requires special static members, emit them |
| 782 * and return true. | 798 * and return true. |
| 783 */ | 799 */ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 805 writeln('}'); | 821 writeln('}'); |
| 806 return true; | 822 return true; |
| 807 case 'SourceEdit': | 823 case 'SourceEdit': |
| 808 docComment([ | 824 docComment([ |
| 809 new dom.Text('Get the result of applying a set of ' + | 825 new dom.Text('Get the result of applying a set of ' + |
| 810 '[edits] to the given [code]. Edits are applied in the order ' + | 826 '[edits] to the given [code]. Edits are applied in the order ' + |
| 811 'they appear in [edits].') | 827 'they appear in [edits].') |
| 812 ]); | 828 ]); |
| 813 writeln( | 829 writeln( |
| 814 'static String applySequence(String code, Iterable<SourceEdit> edits
) =>'); | 830 'static String applySequence(String code, Iterable<SourceEdit> edits
) =>'); |
| 815 writeln(' _applySequence(code, edits);'); | 831 writeln(' applySequenceOfEdits(code, edits);'); |
| 816 return true; | 832 return true; |
| 817 default: | 833 default: |
| 818 return false; | 834 return false; |
| 819 } | 835 } |
| 820 } | 836 } |
| 821 | 837 |
| 822 /** | 838 /** |
| 823 * Emit the toJson() code for an object class. | 839 * Emit the toJson() code for an object class. |
| 824 */ | 840 */ |
| 825 void emitToJsonMember(TypeObject type) { | 841 void emitToJsonMember(TypeObject type) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 } else { | 938 } else { |
| 923 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json)'; | 939 return 'new $typeName.fromJson(jsonDecoder, $jsonPath, $json)'; |
| 924 } | 940 } |
| 925 }); | 941 }); |
| 926 } else { | 942 } else { |
| 927 return fromJsonCode(referencedType); | 943 return fromJsonCode(referencedType); |
| 928 } | 944 } |
| 929 } else { | 945 } else { |
| 930 switch (type.typeName) { | 946 switch (type.typeName) { |
| 931 case 'String': | 947 case 'String': |
| 932 return new FromJsonFunction('jsonDecoder._decodeString'); | 948 return new FromJsonFunction('jsonDecoder.decodeString'); |
| 933 case 'bool': | 949 case 'bool': |
| 934 return new FromJsonFunction('jsonDecoder._decodeBool'); | 950 return new FromJsonFunction('jsonDecoder.decodeBool'); |
| 935 case 'int': | 951 case 'int': |
| 936 case 'long': | 952 case 'long': |
| 937 return new FromJsonFunction('jsonDecoder._decodeInt'); | 953 return new FromJsonFunction('jsonDecoder.decodeInt'); |
| 938 case 'object': | 954 case 'object': |
| 939 return new FromJsonIdentity(); | 955 return new FromJsonIdentity(); |
| 940 default: | 956 default: |
| 941 throw new Exception('Unexpected type name ${type.typeName}'); | 957 throw new Exception('Unexpected type name ${type.typeName}'); |
| 942 } | 958 } |
| 943 } | 959 } |
| 944 } else if (type is TypeMap) { | 960 } else if (type is TypeMap) { |
| 945 FromJsonCode keyCode; | 961 FromJsonCode keyCode; |
| 946 if (dartType(type.keyType) != 'String') { | 962 if (dartType(type.keyType) != 'String') { |
| 947 keyCode = fromJsonCode(type.keyType); | 963 keyCode = fromJsonCode(type.keyType); |
| 948 } else { | 964 } else { |
| 949 keyCode = new FromJsonIdentity(); | 965 keyCode = new FromJsonIdentity(); |
| 950 } | 966 } |
| 951 FromJsonCode valueCode = fromJsonCode(type.valueType); | 967 FromJsonCode valueCode = fromJsonCode(type.valueType); |
| 952 if (keyCode.isIdentity && valueCode.isIdentity) { | 968 if (keyCode.isIdentity && valueCode.isIdentity) { |
| 953 return new FromJsonFunction('jsonDecoder._decodeMap'); | 969 return new FromJsonFunction('jsonDecoder.decodeMap'); |
| 954 } else { | 970 } else { |
| 955 return new FromJsonSnippet((String jsonPath, String json) { | 971 return new FromJsonSnippet((String jsonPath, String json) { |
| 956 StringBuffer result = new StringBuffer(); | 972 StringBuffer result = new StringBuffer(); |
| 957 result.write('jsonDecoder._decodeMap($jsonPath, $json'); | 973 result.write('jsonDecoder.decodeMap($jsonPath, $json'); |
| 958 if (!keyCode.isIdentity) { | 974 if (!keyCode.isIdentity) { |
| 959 result.write(', keyDecoder: ${keyCode.asClosure}'); | 975 result.write(', keyDecoder: ${keyCode.asClosure}'); |
| 960 } | 976 } |
| 961 if (!valueCode.isIdentity) { | 977 if (!valueCode.isIdentity) { |
| 962 result.write(', valueDecoder: ${valueCode.asClosure}'); | 978 result.write(', valueDecoder: ${valueCode.asClosure}'); |
| 963 } | 979 } |
| 964 result.write(')'); | 980 result.write(')'); |
| 965 return result.toString(); | 981 return result.toString(); |
| 966 }); | 982 }); |
| 967 } | 983 } |
| 968 } else if (type is TypeList) { | 984 } else if (type is TypeList) { |
| 969 FromJsonCode itemCode = fromJsonCode(type.itemType); | 985 FromJsonCode itemCode = fromJsonCode(type.itemType); |
| 970 if (itemCode.isIdentity) { | 986 if (itemCode.isIdentity) { |
| 971 return new FromJsonFunction('jsonDecoder._decodeList'); | 987 return new FromJsonFunction('jsonDecoder.decodeList'); |
| 972 } else { | 988 } else { |
| 973 return new FromJsonSnippet((String jsonPath, String json) => | 989 return new FromJsonSnippet((String jsonPath, String json) => |
| 974 'jsonDecoder._decodeList($jsonPath, $json, ${itemCode.asClosure})'); | 990 'jsonDecoder.decodeList($jsonPath, $json, ${itemCode.asClosure})'); |
| 975 } | 991 } |
| 976 } else if (type is TypeUnion) { | 992 } else if (type is TypeUnion) { |
| 977 List<String> decoders = <String>[]; | 993 List<String> decoders = <String>[]; |
| 978 for (TypeDecl choice in type.choices) { | 994 for (TypeDecl choice in type.choices) { |
| 979 TypeDecl resolvedChoice = resolveTypeReferenceChain(choice); | 995 TypeDecl resolvedChoice = resolveTypeReferenceChain(choice); |
| 980 if (resolvedChoice is TypeObject) { | 996 if (resolvedChoice is TypeObject) { |
| 981 TypeObjectField field = resolvedChoice.getField(type.field); | 997 TypeObjectField field = resolvedChoice.getField(type.field); |
| 982 if (field == null) { | 998 if (field == null) { |
| 983 throw new Exception( | 999 throw new Exception( |
| 984 'Each choice in the union needs a field named ${type.field}'); | 1000 'Each choice in the union needs a field named ${type.field}'); |
| 985 } | 1001 } |
| 986 if (field.value == null) { | 1002 if (field.value == null) { |
| 987 throw new Exception( | 1003 throw new Exception( |
| 988 'Each choice in the union needs a constant value for the field $
{type.field}'); | 1004 'Each choice in the union needs a constant value for the field $
{type.field}'); |
| 989 } | 1005 } |
| 990 String closure = fromJsonCode(choice).asClosure; | 1006 String closure = fromJsonCode(choice).asClosure; |
| 991 decoders.add('${literalString(field.value)}: $closure'); | 1007 decoders.add('${literalString(field.value)}: $closure'); |
| 992 } else { | 1008 } else { |
| 993 throw new Exception('Union types must be unions of objects.'); | 1009 throw new Exception('Union types must be unions of objects.'); |
| 994 } | 1010 } |
| 995 } | 1011 } |
| 996 return new FromJsonSnippet((String jsonPath, String json) => | 1012 return new FromJsonSnippet((String jsonPath, String json) => |
| 997 'jsonDecoder._decodeUnion($jsonPath, $json, ${literalString(type.field
)}, {${decoders.join(', ')}})'); | 1013 'jsonDecoder.decodeUnion($jsonPath, $json, ${literalString(type.field)
}, {${decoders.join(', ')}})'); |
| 998 } else { | 1014 } else { |
| 999 throw new Exception("Can't convert $type from JSON"); | 1015 throw new Exception("Can't convert $type from JSON"); |
| 1000 } | 1016 } |
| 1001 } | 1017 } |
| 1002 | 1018 |
| 1003 /** | 1019 /** |
| 1004 * True if the constructor argument for the given field should be optional. | 1020 * True if the constructor argument for the given field should be optional. |
| 1005 */ | 1021 */ |
| 1006 bool isOptionalConstructorArg(String className, TypeObjectField field) { | 1022 bool isOptionalConstructorArg(String className, TypeObjectField field) { |
| 1007 if (field.optional) { | 1023 if (field.optional) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 dartType(type), (String value) => '$value.toJson()'); | 1089 dartType(type), (String value) => '$value.toJson()'); |
| 1074 } else { | 1090 } else { |
| 1075 throw new Exception("Can't convert $resolvedType from JSON"); | 1091 throw new Exception("Can't convert $resolvedType from JSON"); |
| 1076 } | 1092 } |
| 1077 } | 1093 } |
| 1078 | 1094 |
| 1079 @override | 1095 @override |
| 1080 visitApi() { | 1096 visitApi() { |
| 1081 outputHeader(); | 1097 outputHeader(); |
| 1082 writeln(); | 1098 writeln(); |
| 1083 writeln('part of protocol;'); | 1099 writeln('part of analysis_server.plugin.protocol.protocol;'); |
| 1100 writeln(); |
| 1084 emitClasses(); | 1101 emitClasses(); |
| 1085 } | 1102 } |
| 1086 } | 1103 } |
| 1087 | 1104 |
| 1088 /** | 1105 /** |
| 1089 * Container for code that can be used to translate a data type from JSON. | 1106 * Container for code that can be used to translate a data type from JSON. |
| 1090 */ | 1107 */ |
| 1091 abstract class FromJsonCode { | 1108 abstract class FromJsonCode { |
| 1092 /** | 1109 /** |
| 1093 * Get the translation code in the form of a closure. | 1110 * Get the translation code in the form of a closure. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 | 1240 |
| 1224 @override | 1241 @override |
| 1225 String get asClosure => '($type value) => ${callback('value')}'; | 1242 String get asClosure => '($type value) => ${callback('value')}'; |
| 1226 | 1243 |
| 1227 @override | 1244 @override |
| 1228 bool get isIdentity => false; | 1245 bool get isIdentity => false; |
| 1229 | 1246 |
| 1230 @override | 1247 @override |
| 1231 String asSnippet(String value) => callback(value); | 1248 String asSnippet(String value) => callback(value); |
| 1232 } | 1249 } |
| OLD | NEW |