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

Side by Side Diff: pkg/analysis_server/tool/spec/codegen_dart_protocol.dart

Issue 497393002: Make more use of generated code in analysis server. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « pkg/analysis_server/test/socket_server_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'api.dart'; 9 import 'api.dart';
10 import 'codegen_tools.dart'; 10 import 'codegen_tools.dart';
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 static const Map<String, String> _typeRenames = const { 192 static const Map<String, String> _typeRenames = const {
193 'object': 'Object', 193 'object': 'Object',
194 }; 194 };
195 195
196 /** 196 /**
197 * Class members for which the constructor argument should be optional, even 197 * Class members for which the constructor argument should be optional, even
198 * if the member is not an optional part of the protocol. For list types, 198 * if the member is not an optional part of the protocol. For list types,
199 * the constructor will default the member to the empty list. 199 * the constructor will default the member to the empty list.
200 */ 200 */
201 static const Map<String, List<String>> _optionalConstructorArguments = const { 201 static const Map<String, List<String>> _optionalConstructorArguments = const {
202 'ErrorFixes': const ['fixes'],
203 'SourceChange': const ['edits', 'linkedEditGroups'],
202 'SourceFileEdit': const ['edits'], 204 'SourceFileEdit': const ['edits'],
203 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'] 205 'TypeHierarchyItem': const ['interfaces', 'mixins', 'subclasses'],
204 }; 206 };
205 207
206 /** 208 /**
207 * Visitor used to produce doc comments. 209 * Visitor used to produce doc comments.
208 */ 210 */
209 final ToHtmlVisitor toHtmlVisitor; 211 final ToHtmlVisitor toHtmlVisitor;
210 212
211 /** 213 /**
212 * Types implied by the API. This includes types explicitly named in the 214 * Types implied by the API. This includes types explicitly named in the
213 * API as well as those implied by the definitions of requests, responses, 215 * API as well as those implied by the definitions of requests, responses,
(...skipping 29 matching lines...) Expand all
243 writeln(); 245 writeln();
244 emitEnumClass(dartTypeName, type, impliedType); 246 emitEnumClass(dartTypeName, type, impliedType);
245 } 247 }
246 } 248 }
247 } 249 }
248 } 250 }
249 251
250 /** 252 /**
251 * Emit the class to encapsulate an object type. 253 * Emit the class to encapsulate an object type.
252 */ 254 */
253 void emitObjectClass(String className, TypeObject type, ImpliedType 255 void emitObjectClass(String className, TypeObject type,
254 impliedType) { 256 ImpliedType impliedType) {
255 docComment(toHtmlVisitor.collectHtml(() { 257 docComment(toHtmlVisitor.collectHtml(() {
256 toHtmlVisitor.p(() { 258 toHtmlVisitor.p(() {
257 toHtmlVisitor.write(impliedType.humanReadableName); 259 toHtmlVisitor.write(impliedType.humanReadableName);
258 }); 260 });
259 if (impliedType.type != null) { 261 if (impliedType.type != null) {
260 toHtmlVisitor.showType(null, impliedType.type); 262 toHtmlVisitor.showType(null, impliedType.type);
261 } 263 }
262 })); 264 }));
263 writeln('class $className implements HasToJson {'); 265 writeln('class $className implements HasToJson {');
264 indent(() { 266 indent(() {
(...skipping 24 matching lines...) Expand all
289 writeln(); 291 writeln();
290 } 292 }
291 emitToJsonMember(type); 293 emitToJsonMember(type);
292 writeln(); 294 writeln();
293 if (emitToRequestMember(impliedType)) { 295 if (emitToRequestMember(impliedType)) {
294 writeln(); 296 writeln();
295 } 297 }
296 if (emitToResponseMember(impliedType)) { 298 if (emitToResponseMember(impliedType)) {
297 writeln(); 299 writeln();
298 } 300 }
299 if (emitSpecialMembers(className)) { 301 if (emitToNotificationMember(impliedType)) {
302 writeln();
303 }
304 if (emitSpecialMethods(className)) {
300 writeln(); 305 writeln();
301 } 306 }
302 writeln('@override'); 307 writeln('@override');
303 writeln('String toString() => JSON.encode(toJson());'); 308 writeln('String toString() => JSON.encode(toJson());');
304 writeln(); 309 writeln();
305 emitObjectEqualsMember(type, className); 310 emitObjectEqualsMember(type, className);
306 writeln(); 311 writeln();
307 emitObjectHashCode(type); 312 emitObjectHashCode(type);
308 }); 313 });
309 writeln('}'); 314 writeln('}');
310 } 315 }
311 316
312 /** 317 /**
313 * If the class named [className] requires special static members, emit them 318 * If the class named [className] requires special static members, emit them
314 * and return true. 319 * and return true.
315 */ 320 */
316 bool emitSpecialStaticMembers(String className) { 321 bool emitSpecialStaticMembers(String className) {
317 switch (className) { 322 switch (className) {
323 case 'AnalysisError':
324 docComment(
325 [
326 new dom.Text(
327 'Returns a list of AnalysisErrors ' +
328 'correponding to the given list of Engine errors.')]);
329 writeln(
330 'static List<AnalysisError> listFromEngine(engine.LineInfo lineInfo, List<engine.AnalysisError> errors) =>');
331 writeln(' _analysisErrorListFromEngine(lineInfo, errors);');
332 return true;
318 case 'Element': 333 case 'Element':
319 List<String> makeFlagsArgs = <String>[]; 334 List<String> makeFlagsArgs = <String>[];
320 List<String> makeFlagsStatements = <String>[]; 335 List<String> makeFlagsStatements = <String>[];
321 specialElementFlags.forEach((String name, String value) { 336 specialElementFlags.forEach((String name, String value) {
322 String flag = 'FLAG_${name.toUpperCase()}'; 337 String flag = 'FLAG_${name.toUpperCase()}';
323 String camelName = camelJoin(['is', name]); 338 String camelName = camelJoin(['is', name]);
324 writeln('static const int $flag = $value;'); 339 writeln('static const int $flag = $value;');
325 makeFlagsArgs.add('$camelName: false'); 340 makeFlagsArgs.add('$camelName: false');
326 makeFlagsStatements.add('if ($camelName) flags |= $flag;'); 341 makeFlagsStatements.add('if ($camelName) flags |= $flag;');
327 }); 342 });
328 writeln(); 343 writeln();
329 writeln('static int makeFlags({${makeFlagsArgs.join(', ')}}) {'); 344 writeln('static int makeFlags({${makeFlagsArgs.join(', ')}}) {');
330 indent(() { 345 indent(() {
331 writeln('int flags = 0;'); 346 writeln('int flags = 0;');
332 for (String statement in makeFlagsStatements) { 347 for (String statement in makeFlagsStatements) {
333 writeln(statement); 348 writeln(statement);
334 } 349 }
335 writeln('return flags;'); 350 writeln('return flags;');
336 }); 351 });
337 writeln('}'); 352 writeln('}');
338 return true; 353 return true;
339 case 'SourceEdit': 354 case 'SourceEdit':
340 docComment([new dom.Text('Get the result of applying a set of ' + 355 docComment(
341 '[edits] to the given [code]. Edits are applied in the order ' + 356 [
342 'they appear in [edits].')]); 357 new dom.Text(
358 'Get the result of applying a set of ' +
359 '[edits] to the given [code]. Edits are applied in the order ' +
360 'they appear in [edits].')]);
343 writeln( 361 writeln(
344 'static String applySequence(String code, Iterable<SourceEdit> edits ) =>'); 362 'static String applySequence(String code, Iterable<SourceEdit> edits ) =>');
345 writeln(' _applySequence(code, edits);'); 363 writeln(' _applySequence(code, edits);');
346 return true; 364 return true;
347 default: 365 default:
348 return false; 366 return false;
349 } 367 }
350 } 368 }
351 369
352 /** 370 /**
353 * If the class named [className] requires special constructors, emit them 371 * If the class named [className] requires special constructors, emit them
354 * and return true. 372 * and return true.
355 */ 373 */
356 bool emitSpecialConstructors(String className) { 374 bool emitSpecialConstructors(String className) {
357 switch (className) { 375 switch (className) {
358 case 'AnalysisError': 376 case 'AnalysisError':
359 docComment([new dom.Text( 377 docComment(
360 'Construct based on error information from the analyzer engine.')]); 378 [
379 new dom.Text(
380 'Construct based on error information from the analyzer engi ne.')]);
361 writeln( 381 writeln(
362 'factory AnalysisError.fromEngine(engine.LineInfo lineInfo, engine.A nalysisError error) =>' 382 'factory AnalysisError.fromEngine(engine.LineInfo lineInfo, engine.A nalysisError error) =>');
363 );
364 writeln(' _analysisErrorFromEngine(lineInfo, error);'); 383 writeln(' _analysisErrorFromEngine(lineInfo, error);');
365 return true; 384 return true;
385 case 'CompletionSuggestionKind':
386 docComment(
387 [new dom.Text('Construct from an analyzer engine element kind.')]);
388 writeln(
389 'factory CompletionSuggestionKind.fromElementKind(engine.ElementKind kind) =>');
390 writeln(' _completionSuggestionKindFromElementKind(kind);');
391 return true;
366 case 'Element': 392 case 'Element':
367 docComment([new dom.Text('Construct based on a value from the analyzer e ngine.')]); 393 docComment(
394 [new dom.Text('Construct based on a value from the analyzer engine.' )]);
368 writeln('factory Element.fromEngine(engine.Element element) =>'); 395 writeln('factory Element.fromEngine(engine.Element element) =>');
369 writeln(' elementFromEngine(element);'); 396 writeln(' elementFromEngine(element);');
370 return true; 397 return true;
371 case 'ElementKind': 398 case 'ElementKind':
372 docComment([new dom.Text( 399 docComment(
373 'Construct based on a value from the analyzer engine.')]); 400 [new dom.Text('Construct based on a value from the analyzer engine.' )]);
374 writeln('factory ElementKind.fromEngine(engine.ElementKind kind) =>'); 401 writeln('factory ElementKind.fromEngine(engine.ElementKind kind) =>');
375 writeln(' _elementKindFromEngine(kind);'); 402 writeln(' _elementKindFromEngine(kind);');
376 return true; 403 return true;
404 case 'LinkedEditGroup':
405 docComment([new dom.Text('Construct an empty LinkedEditGroup.')]);
406 writeln(
407 'LinkedEditGroup.empty() : this(<Position>[], 0, <LinkedEditSuggesti on>[]);');
408 return true;
377 case 'Location': 409 case 'Location':
378 docComment([new dom.Text( 410 docComment(
379 'Create a Location based on an [engine.Element].')]); 411 [new dom.Text('Create a Location based on an [engine.Element].')]);
380 writeln('factory Location.fromElement(engine.Element element) =>'); 412 writeln('factory Location.fromElement(engine.Element element) =>');
381 writeln(' _locationFromElement(element);'); 413 writeln(' _locationFromElement(element);');
382 writeln(); 414 writeln();
383 docComment([new dom.Text('Create a Location based on an [engine.SearchMa tch].')]); 415 docComment(
416 [new dom.Text('Create a Location based on an [engine.SearchMatch].') ]);
384 writeln('factory Location.fromMatch(engine.SearchMatch match) =>'); 417 writeln('factory Location.fromMatch(engine.SearchMatch match) =>');
385 writeln(' _locationFromMatch(match);'); 418 writeln(' _locationFromMatch(match);');
386 writeln(); 419 writeln();
387 docComment([new dom.Text('Create a Location based on an [engine.AstNode] .')]); 420 docComment(
421 [new dom.Text('Create a Location based on an [engine.AstNode].')]);
388 writeln('factory Location.fromNode(engine.AstNode node) =>'); 422 writeln('factory Location.fromNode(engine.AstNode node) =>');
389 writeln(' _locationFromNode(node);'); 423 writeln(' _locationFromNode(node);');
390 writeln(); 424 writeln();
391 docComment([new dom.Text('Create a Location based on an [engine.Compilat ionUnit].')]); 425 docComment(
392 writeln('factory Location.fromUnit(engine.CompilationUnit unit, engine.S ourceRange range) =>'); 426 [new dom.Text('Create a Location based on an [engine.CompilationUnit ].')]);
427 writeln(
428 'factory Location.fromUnit(engine.CompilationUnit unit, engine.Sourc eRange range) =>');
393 writeln(' _locationFromUnit(unit, range);'); 429 writeln(' _locationFromUnit(unit, range);');
394 return true; 430 return true;
395 case 'OverriddenMember': 431 case 'OverriddenMember':
396 docComment([new dom.Text('Construct based on an element from the analyze r engine.')]); 432 docComment(
397 writeln('factory OverriddenMember.fromEngine(engine.Element member) =>') ; 433 [new dom.Text('Construct based on an element from the analyzer engin e.')]);
434 writeln(
435 'factory OverriddenMember.fromEngine(engine.Element member) =>');
398 writeln(' _overriddenMemberFromEngine(member);'); 436 writeln(' _overriddenMemberFromEngine(member);');
399 return true; 437 return true;
400 case 'RefactoringProblemSeverity': 438 case 'RefactoringProblemSeverity':
401 docComment([new dom.Text('Returns the [RefactoringProblemSeverity] with the maximal severity.')]); 439 docComment(
402 writeln('static RefactoringProblemSeverity max(RefactoringProblemSeverit y a, RefactoringProblemSeverity b) =>'); 440 [
441 new dom.Text(
442 'Returns the [RefactoringProblemSeverity] with the maximal s everity.')]);
443 writeln(
444 'static RefactoringProblemSeverity max(RefactoringProblemSeverity a, RefactoringProblemSeverity b) =>');
403 writeln(' _maxRefactoringProblemSeverity(a, b);'); 445 writeln(' _maxRefactoringProblemSeverity(a, b);');
404 return true; 446 return true;
405 case 'SearchResult': 447 case 'SearchResult':
406 docComment([new dom.Text('Construct based on a value from the search eng ine.')]); 448 docComment(
449 [new dom.Text('Construct based on a value from the search engine.')] );
407 writeln('factory SearchResult.fromMatch(engine.SearchMatch match) =>'); 450 writeln('factory SearchResult.fromMatch(engine.SearchMatch match) =>');
408 writeln(' searchResultFromMatch(match);'); 451 writeln(' searchResultFromMatch(match);');
409 return true; 452 return true;
410 case 'SearchResultKind': 453 case 'SearchResultKind':
411 docComment([new dom.Text('Construct based on a value from the search eng ine.')]); 454 docComment(
412 writeln('factory SearchResultKind.fromEngine(engine.MatchKind kind) =>') ; 455 [new dom.Text('Construct based on a value from the search engine.')] );
456 writeln(
457 'factory SearchResultKind.fromEngine(engine.MatchKind kind) =>');
413 writeln(' _searchResultKindFromEngine(kind);'); 458 writeln(' _searchResultKindFromEngine(kind);');
414 return true; 459 return true;
415 case 'SourceEdit': 460 case 'SourceEdit':
416 docComment([new dom.Text('Construct based on a SourceRange.')]); 461 docComment([new dom.Text('Construct based on a SourceRange.')]);
417 writeln( 462 writeln(
418 'SourceEdit.range(engine.SourceRange range, String replacement, {Str ing id})'); 463 'SourceEdit.range(engine.SourceRange range, String replacement, {Str ing id})');
419 writeln(' : this(range.offset, range.length, replacement, id: id);'); 464 writeln(' : this(range.offset, range.length, replacement, id: id);');
420 return true; 465 return true;
421 default: 466 default:
422 return false; 467 return false;
423 } 468 }
424 } 469 }
425 470
426 /** 471 /**
427 * If the class named [className] requires special getters, emit them and 472 * If the class named [className] requires special getters, emit them and
428 * return true. 473 * return true.
429 */ 474 */
430 bool emitSpecialGetters(String className) { 475 bool emitSpecialGetters(String className) {
431 switch (className) { 476 switch (className) {
432 case 'Element': 477 case 'Element':
433 for (String name in specialElementFlags.keys) { 478 for (String name in specialElementFlags.keys) {
434 String flag = 'FLAG_${name.toUpperCase()}'; 479 String flag = 'FLAG_${name.toUpperCase()}';
435 writeln('bool get ${camelJoin(['is', name])} => (flags & $flag) != 0;' 480 writeln(
436 ); 481 'bool get ${camelJoin(['is', name])} => (flags & $flag) != 0;');
437 } 482 }
438 return true; 483 return true;
439 case 'SourceEdit': 484 case 'SourceEdit':
440 docComment([new dom.Text('The end of the region to be modified.')]); 485 docComment([new dom.Text('The end of the region to be modified.')]);
441 writeln('int get end => offset + length;'); 486 writeln('int get end => offset + length;');
442 return true; 487 return true;
443 default: 488 default:
444 return false; 489 return false;
445 } 490 }
446 } 491 }
447 492
448 /** 493 /**
449 * If the class named [className] requires special members, emit them and 494 * If the class named [className] requires special methods, emit them and
450 * return true. 495 * return true.
451 */ 496 */
452 bool emitSpecialMembers(String className) { 497 bool emitSpecialMethods(String className) {
453 switch (className) { 498 switch (className) {
499 case 'ErrorFixes':
500 docComment([new dom.Text('Add a [Fix]')]);
501 writeln('void addFix(Fix fix) {');
502 indent(() {
503 writeln('fixes.add(fix.change);');
504 });
505 writeln('}');
506 return true;
507 case 'LinkedEditGroup':
508 docComment([new dom.Text('Add a new position and change the length.')]);
509 writeln('void addPosition(Position position, int length) {');
510 indent(() {
511 writeln('positions.add(position);');
512 writeln('this.length = length;');
513 });
514 writeln('}');
515 writeln();
516 docComment([new dom.Text('Add a new suggestion.')]);
517 writeln('void addSuggestion(LinkedEditSuggestion suggestion) {');
518 indent(() {
519 writeln('suggestions.add(suggestion);');
520 });
521 writeln('}');
522 return true;
523 case 'SourceChange':
524 docComment(
525 [new dom.Text('Adds [edit] to the [FileEdit] for the given [file].') ]);
526 writeln('void addEdit(String file, SourceEdit edit) =>');
527 writeln(' _addEditToSourceChange(this, file, edit);');
528 writeln();
529 docComment([new dom.Text('Adds the given [FileEdit].')]);
530 writeln('void addFileEdit(SourceFileEdit edit) {');
531 indent(() {
532 writeln('edits.add(edit);');
533 });
534 writeln('}');
535 writeln();
536 docComment([new dom.Text('Adds the given [LinkedEditGroup].')]);
537 writeln('void addLinkedEditGroup(LinkedEditGroup linkedEditGroup) {');
538 indent(() {
539 writeln('linkedEditGroups.add(linkedEditGroup);');
540 });
541 writeln('}');
542 writeln();
543 docComment(
544 [new dom.Text('Returns the [FileEdit] for the given [file], maybe `n ull`.')]);
545 writeln('SourceFileEdit getFileEdit(String file) =>');
546 writeln(' _getChangeFileEdit(this, file);');
547 return true;
454 case 'SourceEdit': 548 case 'SourceEdit':
455 docComment([new dom.Text( 549 docComment(
456 'Get the result of applying the edit to the given [code].')]); 550 [new dom.Text('Get the result of applying the edit to the given [cod e].')]);
457 writeln('String apply(String code) => _applyEdit(code, this);'); 551 writeln('String apply(String code) => _applyEdit(code, this);');
458 return true; 552 return true;
459 case 'SourceFileEdit': 553 case 'SourceFileEdit':
460 docComment([new dom.Text('Adds the given [Edit] to the list.')]); 554 docComment([new dom.Text('Adds the given [Edit] to the list.')]);
461 writeln('void add(SourceEdit edit) => _addEditForSource(this, edit);'); 555 writeln('void add(SourceEdit edit) => _addEditForSource(this, edit);');
462 writeln(); 556 writeln();
463 docComment([new dom.Text('Adds the given [Edit]s.')]); 557 docComment([new dom.Text('Adds the given [Edit]s.')]);
464 writeln('void addAll(Iterable<SourceEdit> edits) =>'); 558 writeln('void addAll(Iterable<SourceEdit> edits) =>');
465 writeln(' _addAllEditsForSource(this, edits);'); 559 writeln(' _addAllEditsForSource(this, edits);');
466 return true; 560 return true;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 } 659 }
566 660
567 /** 661 /**
568 * Emit the toRequest() code for a class, if appropriate. Returns true if 662 * Emit the toRequest() code for a class, if appropriate. Returns true if
569 * code was emitted. 663 * code was emitted.
570 */ 664 */
571 bool emitToRequestMember(ImpliedType impliedType) { 665 bool emitToRequestMember(ImpliedType impliedType) {
572 if (impliedType.kind == 'requestParams') { 666 if (impliedType.kind == 'requestParams') {
573 writeln('Request toRequest(String id) {'); 667 writeln('Request toRequest(String id) {');
574 indent(() { 668 indent(() {
575 String methodString = literalString((impliedType.apiNode as 669 String methodString =
576 Request).longMethod); 670 literalString((impliedType.apiNode as Request).longMethod);
577 writeln('return new Request(id, $methodString, toJson());'); 671 writeln('return new Request(id, $methodString, toJson());');
578 }); 672 });
579 writeln('}'); 673 writeln('}');
580 return true; 674 return true;
581 } 675 }
582 return false; 676 return false;
583 } 677 }
584 678
585 /** 679 /**
586 * Emit the toResponse() code for a class, if appropriate. Returns true if 680 * Emit the toResponse() code for a class, if appropriate. Returns true if
587 * code was emitted. 681 * code was emitted.
588 */ 682 */
589 bool emitToResponseMember(ImpliedType impliedType) { 683 bool emitToResponseMember(ImpliedType impliedType) {
590 if (impliedType.kind == 'requestResult') { 684 if (impliedType.kind == 'requestResult') {
591 writeln('Response toResponse(String id) {'); 685 writeln('Response toResponse(String id) {');
592 indent(() { 686 indent(() {
593 writeln('return new Response(id, result: toJson());'); 687 writeln('return new Response(id, result: toJson());');
594 }); 688 });
595 writeln('}'); 689 writeln('}');
596 return true; 690 return true;
597 } 691 }
598 return false; 692 return false;
599 } 693 }
600 694
601 /** 695 /**
696 * Emit the toNotification() code for a class, if appropriate. Returns true
697 * if code was emitted.
698 */
699 bool emitToNotificationMember(ImpliedType impliedType) {
700 if (impliedType.kind == 'notificationParams') {
701 writeln('Notification toNotification() {');
702 indent(() {
703 String eventString =
704 literalString((impliedType.apiNode as Notification).longEvent);
705 writeln('return new Notification($eventString, toJson());');
706 });
707 writeln('}');
708 return true;
709 }
710 return false;
711 }
712
713 /**
602 * Emit the operator== code for an object class. 714 * Emit the operator== code for an object class.
603 */ 715 */
604 void emitObjectEqualsMember(TypeObject type, String className) { 716 void emitObjectEqualsMember(TypeObject type, String className) {
605 writeln('@override'); 717 writeln('@override');
606 writeln('bool operator==(other) {'); 718 writeln('bool operator==(other) {');
607 indent(() { 719 indent(() {
608 writeln('if (other is $className) {'); 720 writeln('if (other is $className) {');
609 indent(() { 721 indent(() {
610 var comparisons = <String>[]; 722 var comparisons = <String>[];
611 for (TypeObjectField field in type.fields) { 723 for (TypeObjectField field in type.fields) {
612 if (field.value != null) { 724 if (field.value != null) {
613 continue; 725 continue;
614 } 726 }
615 comparisons.add(compareEqualsCode(field.type, field.name, 727 comparisons.add(
616 'other.${field.name}')); 728 compareEqualsCode(field.type, field.name, 'other.${field.name}'));
617 } 729 }
618 if (comparisons.isEmpty) { 730 if (comparisons.isEmpty) {
619 writeln('return true;'); 731 writeln('return true;');
620 } else { 732 } else {
621 String concatenated = comparisons.join(' &&\n '); 733 String concatenated = comparisons.join(' &&\n ');
622 writeln('return $concatenated;'); 734 writeln('return $concatenated;');
623 } 735 }
624 }); 736 });
625 writeln('}'); 737 writeln('}');
626 writeln('return false;'); 738 writeln('return false;');
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 emitEnumClassConstructor(className, type); 795 emitEnumClassConstructor(className, type);
684 writeln(); 796 writeln();
685 emitEnumFromJsonConstructor(className, type, impliedType); 797 emitEnumFromJsonConstructor(className, type, impliedType);
686 writeln(); 798 writeln();
687 if (emitSpecialConstructors(className)) { 799 if (emitSpecialConstructors(className)) {
688 writeln(); 800 writeln();
689 } 801 }
690 if (emitSpecialGetters(className)) { 802 if (emitSpecialGetters(className)) {
691 writeln(); 803 writeln();
692 } 804 }
693 if (emitSpecialMembers(className)) { 805 if (emitSpecialMethods(className)) {
694 writeln(); 806 writeln();
695 } 807 }
696 writeln('@override'); 808 writeln('@override');
697 writeln('String toString() => "$className.\$name";'); 809 writeln('String toString() => "$className.\$name";');
698 writeln(); 810 writeln();
699 writeln('String toJson() => name;'); 811 writeln('String toJson() => name;');
700 }); 812 });
701 writeln('}'); 813 writeln('}');
702 } 814 }
703 815
(...skipping 24 matching lines...) Expand all
728 */ 840 */
729 ToJsonCode toJsonCode(TypeDecl type) { 841 ToJsonCode toJsonCode(TypeDecl type) {
730 TypeDecl resolvedType = resolveTypeReferenceChain(type); 842 TypeDecl resolvedType = resolveTypeReferenceChain(type);
731 if (resolvedType is TypeReference) { 843 if (resolvedType is TypeReference) {
732 return new ToJsonIdentity(dartType(type)); 844 return new ToJsonIdentity(dartType(type));
733 } else if (resolvedType is TypeList) { 845 } else if (resolvedType is TypeList) {
734 ToJsonCode itemCode = toJsonCode(resolvedType.itemType); 846 ToJsonCode itemCode = toJsonCode(resolvedType.itemType);
735 if (itemCode.isIdentity) { 847 if (itemCode.isIdentity) {
736 return new ToJsonIdentity(dartType(type)); 848 return new ToJsonIdentity(dartType(type));
737 } else { 849 } else {
738 return new ToJsonSnippet(dartType(type), (String value) => 850 return new ToJsonSnippet(
739 '$value.map(${itemCode.asClosure}).toList()'); 851 dartType(type),
852 (String value) => '$value.map(${itemCode.asClosure}).toList()');
740 } 853 }
741 } else if (resolvedType is TypeMap) { 854 } else if (resolvedType is TypeMap) {
742 ToJsonCode keyCode; 855 ToJsonCode keyCode;
743 if (dartType(resolvedType.keyType) != 'String') { 856 if (dartType(resolvedType.keyType) != 'String') {
744 keyCode = toJsonCode(resolvedType.keyType); 857 keyCode = toJsonCode(resolvedType.keyType);
745 } else { 858 } else {
746 keyCode = new ToJsonIdentity(dartType(resolvedType.keyType)); 859 keyCode = new ToJsonIdentity(dartType(resolvedType.keyType));
747 } 860 }
748 ToJsonCode valueCode = toJsonCode(resolvedType.valueType); 861 ToJsonCode valueCode = toJsonCode(resolvedType.valueType);
749 if (keyCode.isIdentity && valueCode.isIdentity) { 862 if (keyCode.isIdentity && valueCode.isIdentity) {
(...skipping 11 matching lines...) Expand all
761 result.write(')'); 874 result.write(')');
762 return result.toString(); 875 return result.toString();
763 }); 876 });
764 } 877 }
765 } else if (resolvedType is TypeUnion) { 878 } else if (resolvedType is TypeUnion) {
766 for (TypeDecl choice in resolvedType.choices) { 879 for (TypeDecl choice in resolvedType.choices) {
767 if (resolveTypeReferenceChain(choice) is! TypeObject) { 880 if (resolveTypeReferenceChain(choice) is! TypeObject) {
768 throw new Exception('Union types must be unions of objects'); 881 throw new Exception('Union types must be unions of objects');
769 } 882 }
770 } 883 }
771 return new ToJsonSnippet(dartType(type), (String value) => 884 return new ToJsonSnippet(
772 '$value.toJson()'); 885 dartType(type),
886 (String value) => '$value.toJson()');
773 } else if (resolvedType is TypeObject || resolvedType is TypeEnum) { 887 } else if (resolvedType is TypeObject || resolvedType is TypeEnum) {
774 return new ToJsonSnippet(dartType(type), (String value) => 888 return new ToJsonSnippet(
775 '$value.toJson()'); 889 dartType(type),
890 (String value) => '$value.toJson()');
776 } else { 891 } else {
777 throw new Exception("Can't convert $resolvedType from JSON"); 892 throw new Exception("Can't convert $resolvedType from JSON");
778 } 893 }
779 } 894 }
780 895
781 /** 896 /**
782 * Compute the code necessary to compare two objects for equality. 897 * Compute the code necessary to compare two objects for equality.
783 */ 898 */
784 String compareEqualsCode(TypeDecl type, String thisVar, String otherVar) { 899 String compareEqualsCode(TypeDecl type, String thisVar, String otherVar) {
785 TypeDecl resolvedType = resolveTypeReferenceChain(type); 900 TypeDecl resolvedType = resolveTypeReferenceChain(type);
786 if (resolvedType is TypeReference || resolvedType is TypeEnum || 901 if (resolvedType is TypeReference ||
787 resolvedType is TypeObject || resolvedType is TypeUnion) { 902 resolvedType is TypeEnum ||
903 resolvedType is TypeObject ||
904 resolvedType is TypeUnion) {
788 return '$thisVar == $otherVar'; 905 return '$thisVar == $otherVar';
789 } else if (resolvedType is TypeList) { 906 } else if (resolvedType is TypeList) {
790 String itemTypeName = dartType(resolvedType.itemType); 907 String itemTypeName = dartType(resolvedType.itemType);
791 String subComparison = compareEqualsCode(resolvedType.itemType, 'a', 'b'); 908 String subComparison = compareEqualsCode(resolvedType.itemType, 'a', 'b');
792 String closure = '($itemTypeName a, $itemTypeName b) => $subComparison'; 909 String closure = '($itemTypeName a, $itemTypeName b) => $subComparison';
793 return '_listEqual($thisVar, $otherVar, $closure)'; 910 return '_listEqual($thisVar, $otherVar, $closure)';
794 } else if (resolvedType is TypeMap) { 911 } else if (resolvedType is TypeMap) {
795 String valueTypeName = dartType(resolvedType.valueType); 912 String valueTypeName = dartType(resolvedType.valueType);
796 String subComparison = compareEqualsCode(resolvedType.valueType, 'a', 'b' 913 String subComparison =
797 ); 914 compareEqualsCode(resolvedType.valueType, 'a', 'b');
798 String closure = '($valueTypeName a, $valueTypeName b) => $subComparison'; 915 String closure = '($valueTypeName a, $valueTypeName b) => $subComparison';
799 return '_mapEqual($thisVar, $otherVar, $closure)'; 916 return '_mapEqual($thisVar, $otherVar, $closure)';
800 } 917 }
801 throw new Exception("Don't know how to compare for equality: $resolvedType" 918 throw new Exception(
802 ); 919 "Don't know how to compare for equality: $resolvedType");
803 } 920 }
804 921
805 /** 922 /**
806 * Emit the method for decoding an object from JSON. 923 * Emit the method for decoding an object from JSON.
807 */ 924 */
808 void emitObjectFromJsonConstructor(String className, TypeObject 925 void emitObjectFromJsonConstructor(String className, TypeObject type,
809 type, ImpliedType impliedType) { 926 ImpliedType impliedType) {
810 String humanReadableNameString = literalString(impliedType.humanReadableName 927 String humanReadableNameString =
811 ); 928 literalString(impliedType.humanReadableName);
812 writeln( 929 writeln(
813 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O bject json) {' 930 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O bject json) {');
814 );
815 indent(() { 931 indent(() {
816 writeln('if (json == null) {'); 932 writeln('if (json == null) {');
817 indent(() { 933 indent(() {
818 writeln('json = {};'); 934 writeln('json = {};');
819 }); 935 });
820 writeln('}'); 936 writeln('}');
821 writeln('if (json is Map) {'); 937 writeln('if (json is Map) {');
822 indent(() { 938 indent(() {
823 List<String> args = <String>[]; 939 List<String> args = <String>[];
824 List<String> optionalArgs = <String>[]; 940 List<String> optionalArgs = <String>[];
(...skipping 14 matching lines...) Expand all
839 if (isOptionalConstructorArg(className, field)) { 955 if (isOptionalConstructorArg(className, field)) {
840 optionalArgs.add('${field.name}: ${field.name}'); 956 optionalArgs.add('${field.name}: ${field.name}');
841 } else { 957 } else {
842 args.add(field.name); 958 args.add(field.name);
843 } 959 }
844 TypeDecl fieldType = field.type; 960 TypeDecl fieldType = field.type;
845 String fieldDartType = dartType(fieldType); 961 String fieldDartType = dartType(fieldType);
846 writeln('$fieldDartType ${field.name};'); 962 writeln('$fieldDartType ${field.name};');
847 writeln('if (json.containsKey($fieldNameString)) {'); 963 writeln('if (json.containsKey($fieldNameString)) {');
848 indent(() { 964 indent(() {
849 String toJson = fromJsonCode(fieldType).asSnippet(jsonPath, 965 String toJson =
850 fieldAccessor); 966 fromJsonCode(fieldType).asSnippet(jsonPath, fieldAccessor);
851 writeln('${field.name} = $toJson;'); 967 writeln('${field.name} = $toJson;');
852 }); 968 });
853 write('}'); 969 write('}');
854 if (!field.optional) { 970 if (!field.optional) {
855 writeln(' else {'); 971 writeln(' else {');
856 indent(() { 972 indent(() {
857 writeln( 973 writeln(
858 "throw jsonDecoder.missingKey(jsonPath, $fieldNameString);"); 974 "throw jsonDecoder.missingKey(jsonPath, $fieldNameString);");
859 }); 975 });
860 writeln('}'); 976 writeln('}');
(...skipping 16 matching lines...) Expand all
877 'throw jsonDecoder.mismatch(jsonPath, $humanReadableNameString);'); 993 'throw jsonDecoder.mismatch(jsonPath, $humanReadableNameString);');
878 }); 994 });
879 writeln('}'); 995 writeln('}');
880 }); 996 });
881 writeln('}'); 997 writeln('}');
882 } 998 }
883 999
884 /** 1000 /**
885 * Emit the method for decoding an enum from JSON. 1001 * Emit the method for decoding an enum from JSON.
886 */ 1002 */
887 void emitEnumFromJsonConstructor(String className, TypeEnum type, ImpliedType 1003 void emitEnumFromJsonConstructor(String className, TypeEnum type,
888 impliedType) { 1004 ImpliedType impliedType) {
889 writeln( 1005 writeln(
890 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O bject json) {' 1006 'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, O bject json) {');
891 );
892 indent(() { 1007 indent(() {
893 writeln('if (json is String) {'); 1008 writeln('if (json is String) {');
894 indent(() { 1009 indent(() {
895 writeln('try {'); 1010 writeln('try {');
896 indent(() { 1011 indent(() {
897 writeln('return new $className(json);'); 1012 writeln('return new $className(json);');
898 }); 1013 });
899 writeln('} catch(_) {'); 1014 writeln('} catch(_) {');
900 indent(() { 1015 indent(() {
901 writeln('// Fall through'); 1016 writeln('// Fall through');
902 }); 1017 });
903 writeln('}'); 1018 writeln('}');
904 }); 1019 });
905 writeln('}'); 1020 writeln('}');
906 String humanReadableNameString = literalString( 1021 String humanReadableNameString =
907 impliedType.humanReadableName); 1022 literalString(impliedType.humanReadableName);
908 writeln('throw jsonDecoder.mismatch(jsonPath, $humanReadableNameString);' 1023 writeln(
909 ); 1024 'throw jsonDecoder.mismatch(jsonPath, $humanReadableNameString);');
910 }); 1025 });
911 writeln('}'); 1026 writeln('}');
912 } 1027 }
913 1028
914 /** 1029 /**
915 * Compute the code necessary to translate [type] from JSON. 1030 * Compute the code necessary to translate [type] from JSON.
916 */ 1031 */
917 FromJsonCode fromJsonCode(TypeDecl type) { 1032 FromJsonCode fromJsonCode(TypeDecl type) {
918 if (type is TypeReference) { 1033 if (type is TypeReference) {
919 TypeDefinition referencedDefinition = api.types[type.typeName]; 1034 TypeDefinition referencedDefinition = api.types[type.typeName];
920 if (referencedDefinition != null) { 1035 if (referencedDefinition != null) {
921 TypeDecl referencedType = referencedDefinition.type; 1036 TypeDecl referencedType = referencedDefinition.type;
922 if (referencedType is TypeObject || referencedType is TypeEnum) { 1037 if (referencedType is TypeObject || referencedType is TypeEnum) {
923 return new FromJsonSnippet((String jsonPath, String json) => 1038 return new FromJsonSnippet(
924 'new ${dartType(type)}.fromJson(jsonDecoder, $jsonPath, $json)'); 1039 (String jsonPath, String json) =>
1040 'new ${dartType(type)}.fromJson(jsonDecoder, $jsonPath, $json) ');
925 } else { 1041 } else {
926 return fromJsonCode(referencedType); 1042 return fromJsonCode(referencedType);
927 } 1043 }
928 } else { 1044 } else {
929 switch (type.typeName) { 1045 switch (type.typeName) {
930 case 'String': 1046 case 'String':
931 return new FromJsonFunction('jsonDecoder._decodeString'); 1047 return new FromJsonFunction('jsonDecoder._decodeString');
932 case 'bool': 1048 case 'bool':
933 return new FromJsonFunction('jsonDecoder._decodeBool'); 1049 return new FromJsonFunction('jsonDecoder._decodeBool');
934 case 'int': 1050 case 'int':
(...skipping 26 matching lines...) Expand all
961 } 1077 }
962 result.write(')'); 1078 result.write(')');
963 return result.toString(); 1079 return result.toString();
964 }); 1080 });
965 } 1081 }
966 } else if (type is TypeList) { 1082 } else if (type is TypeList) {
967 FromJsonCode itemCode = fromJsonCode(type.itemType); 1083 FromJsonCode itemCode = fromJsonCode(type.itemType);
968 if (itemCode.isIdentity) { 1084 if (itemCode.isIdentity) {
969 return new FromJsonFunction('jsonDecoder._decodeList'); 1085 return new FromJsonFunction('jsonDecoder._decodeList');
970 } else { 1086 } else {
971 return new FromJsonSnippet((String jsonPath, String json) => 1087 return new FromJsonSnippet(
972 'jsonDecoder._decodeList($jsonPath, $json, ${itemCode.asClosure})'); 1088 (String jsonPath, String json) =>
1089 'jsonDecoder._decodeList($jsonPath, $json, ${itemCode.asClosure} )');
973 } 1090 }
974 } else if (type is TypeUnion) { 1091 } else if (type is TypeUnion) {
975 List<String> decoders = <String>[]; 1092 List<String> decoders = <String>[];
976 for (TypeDecl choice in type.choices) { 1093 for (TypeDecl choice in type.choices) {
977 TypeDecl resolvedChoice = resolveTypeReferenceChain(choice); 1094 TypeDecl resolvedChoice = resolveTypeReferenceChain(choice);
978 if (resolvedChoice is TypeObject) { 1095 if (resolvedChoice is TypeObject) {
979 TypeObjectField field = resolvedChoice.getField(type.field); 1096 TypeObjectField field = resolvedChoice.getField(type.field);
980 if (field == null) { 1097 if (field == null) {
981 throw new Exception( 1098 throw new Exception(
982 'Each choice in the union needs a field named ${type.field}'); 1099 'Each choice in the union needs a field named ${type.field}');
983 } 1100 }
984 if (field.value == null) { 1101 if (field.value == null) {
985 throw new Exception( 1102 throw new Exception(
986 'Each choice in the union needs a constant value for the field $ {type.field}'); 1103 'Each choice in the union needs a constant value for the field $ {type.field}');
987 } 1104 }
988 String closure = fromJsonCode(choice).asClosure; 1105 String closure = fromJsonCode(choice).asClosure;
989 decoders.add('${literalString(field.value)}: $closure'); 1106 decoders.add('${literalString(field.value)}: $closure');
990 } else { 1107 } else {
991 throw new Exception('Union types must be unions of objects.'); 1108 throw new Exception('Union types must be unions of objects.');
992 } 1109 }
993 } 1110 }
994 return new FromJsonSnippet((String jsonPath, String json) => 1111 return new FromJsonSnippet(
995 'jsonDecoder._decodeUnion($jsonPath, $json, ${literalString(type.field )}, {${decoders.join(', ')}})' 1112 (String jsonPath, String json) =>
996 ); 1113 'jsonDecoder._decodeUnion($jsonPath, $json, ${literalString(type.f ield)}, {${decoders.join(', ')}})');
997 } else { 1114 } else {
998 throw new Exception("Can't convert $type from JSON"); 1115 throw new Exception("Can't convert $type from JSON");
999 } 1116 }
1000 } 1117 }
1001 1118
1002 /** 1119 /**
1003 * Emit a convenience constructor for decoding a piece of protocol, if 1120 * Emit a convenience constructor for decoding a piece of protocol, if
1004 * appropriate. Return true if a constructor was emitted. 1121 * appropriate. Return true if a constructor was emitted.
1005 */ 1122 */
1006 bool emitConvenienceConstructor(String className, ImpliedType impliedType) { 1123 bool emitConvenienceConstructor(String className, ImpliedType impliedType) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 } else if (type is TypeMap) { 1215 } else if (type is TypeMap) {
1099 return 'Map<${dartType(type.keyType)}, ${dartType(type.valueType)}>'; 1216 return 'Map<${dartType(type.keyType)}, ${dartType(type.valueType)}>';
1100 } else if (type is TypeUnion) { 1217 } else if (type is TypeUnion) {
1101 return 'dynamic'; 1218 return 'dynamic';
1102 } else { 1219 } else {
1103 throw new Exception("Can't convert to a dart type"); 1220 throw new Exception("Can't convert to a dart type");
1104 } 1221 }
1105 } 1222 }
1106 } 1223 }
1107 1224
1108 final GeneratedFile target = new GeneratedFile( 1225 final GeneratedFile target =
1109 '../../lib/src/generated_protocol.dart', () { 1226 new GeneratedFile('../../lib/src/generated_protocol.dart', () {
1110 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi()); 1227 CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi());
1111 return visitor.collectCode(visitor.visitApi); 1228 return visitor.collectCode(visitor.visitApi);
1112 }); 1229 });
1113 1230
1114 /** 1231 /**
1115 * Translate spec_input.html into protocol_matchers.dart. 1232 * Translate spec_input.html into protocol_matchers.dart.
1116 */ 1233 */
1117 main() { 1234 main() {
1118 target.generate(); 1235 target.generate();
1119 } 1236 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/test/socket_server_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698