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

Side by Side Diff: pkg/analysis_server/lib/src/utilities/change_builder_dart.dart

Issue 2866603002: Remove the use of CorrectionUtilities (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analysis_server/lib/src/provisional/edit/utilities/change_builder_dart.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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 6
7 import 'package:analysis_server/protocol/protocol_generated.dart' 7 import 'package:analysis_server/protocol/protocol_generated.dart'
8 hide Element, ElementKind; 8 hide Element, ElementKind;
9 import 'package:analysis_server/src/provisional/edit/utilities/change_builder_co re.dart'; 9 import 'package:analysis_server/src/provisional/edit/utilities/change_builder_co re.dart';
10 import 'package:analysis_server/src/provisional/edit/utilities/change_builder_da rt.dart'; 10 import 'package:analysis_server/src/provisional/edit/utilities/change_builder_da rt.dart';
11 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; 11 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
12 import 'package:analysis_server/src/services/correction/source_range.dart'; 12 import 'package:analysis_server/src/services/correction/source_range.dart';
13 import 'package:analysis_server/src/services/correction/util.dart'; 13 import 'package:analysis_server/src/services/correction/util.dart';
14 import 'package:analysis_server/src/utilities/change_builder_core.dart'; 14 import 'package:analysis_server/src/utilities/change_builder_core.dart';
15 import 'package:analyzer/dart/ast/ast.dart'; 15 import 'package:analyzer/dart/ast/ast.dart';
16 import 'package:analyzer/dart/ast/token.dart'; 16 import 'package:analyzer/dart/ast/token.dart';
17 import 'package:analyzer/dart/element/element.dart'; 17 import 'package:analyzer/dart/element/element.dart';
18 import 'package:analyzer/dart/element/type.dart'; 18 import 'package:analyzer/dart/element/type.dart';
19 import 'package:analyzer/src/dart/analysis/driver.dart'; 19 import 'package:analyzer/src/dart/analysis/driver.dart';
20 import 'package:analyzer/src/dart/ast/utilities.dart';
21 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
20 import 'package:analyzer/src/generated/resolver.dart'; 22 import 'package:analyzer/src/generated/resolver.dart';
21 import 'package:analyzer/src/generated/source.dart'; 23 import 'package:analyzer/src/generated/source.dart';
22 import 'package:analyzer/src/generated/utilities_dart.dart'; 24 import 'package:analyzer/src/generated/utilities_dart.dart';
23 25
24 /** 26 /**
25 * A [ChangeBuilder] used to build changes in Dart files. 27 * A [ChangeBuilder] used to build changes in Dart files.
26 */ 28 */
27 class DartChangeBuilderImpl extends ChangeBuilderImpl 29 class DartChangeBuilderImpl extends ChangeBuilderImpl
28 implements DartChangeBuilder { 30 implements DartChangeBuilder {
29 /** 31 /**
(...skipping 12 matching lines...) Expand all
42 AnalysisResult result = await driver.getResult(path); 44 AnalysisResult result = await driver.getResult(path);
43 return new DartFileEditBuilderImpl(this, path, fileStamp, result.unit); 45 return new DartFileEditBuilderImpl(this, path, fileStamp, result.unit);
44 } 46 }
45 } 47 }
46 48
47 /** 49 /**
48 * An [EditBuilder] used to build edits in Dart files. 50 * An [EditBuilder] used to build edits in Dart files.
49 */ 51 */
50 class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder { 52 class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
51 /** 53 /**
52 * A utility class used to help build the source code.
53 */
54 final CorrectionUtils utils;
55
56 /**
57 * Initialize a newly created builder to build a source edit. 54 * Initialize a newly created builder to build a source edit.
58 */ 55 */
59 DartEditBuilderImpl( 56 DartEditBuilderImpl(
60 DartFileEditBuilderImpl sourceFileEditBuilder, int offset, int length) 57 DartFileEditBuilderImpl sourceFileEditBuilder, int offset, int length)
61 : utils = sourceFileEditBuilder.utils, 58 : super(sourceFileEditBuilder, offset, length);
62 super(sourceFileEditBuilder, offset, length);
63 59
64 DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder; 60 DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder;
65 61
66 @override 62 @override
67 void set targetClassElement(ClassElement element) {
68 utils.targetClassElement = element;
69 }
70
71 @override
72 LinkedEditBuilderImpl createLinkedEditBuilder() { 63 LinkedEditBuilderImpl createLinkedEditBuilder() {
73 return new DartLinkedEditBuilderImpl(this); 64 return new DartLinkedEditBuilderImpl(this);
74 } 65 }
75 66
76 /** 67 /**
77 * Returns the indentation with the given [level]. 68 * Returns the indentation with the given [level].
78 */ 69 */
79 String getIndent(int level) => ' ' * level; 70 String getIndent(int level) => ' ' * level;
80 71
81 // /**
82 // * Arrange to have imports added for each of the given [libraries].
83 // */
84 // void importLibraries(Iterable<Source> libraries) {
85 // dartFileEditBuilder.importLibraries(libraries);
86 // }
87
88 /** 72 /**
89 * Arrange to have an import added for the given [library]. 73 * Arrange to have an import added for the given [library].
90 */ 74 */
91 void importLibrary(Source library) { 75 void importLibrary(Source library) {
92 dartFileEditBuilder.librariesToImport.add(library); 76 dartFileEditBuilder.librariesToImport.add(library);
93 } 77 }
94 78
95 @override 79 @override
96 void writeClassDeclaration(String name, 80 void writeClassDeclaration(String name,
97 {Iterable<DartType> interfaces, 81 {Iterable<DartType> interfaces,
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 } 451 }
468 writeParameterMatchingArgument(argument, i, usedNames); 452 writeParameterMatchingArgument(argument, i, usedNames);
469 } 453 }
470 if (hasNamedParameters) { 454 if (hasNamedParameters) {
471 write('}'); 455 write('}');
472 } 456 }
473 } 457 }
474 458
475 @override 459 @override
476 void writeParameterSource(DartType type, String name) { 460 void writeParameterSource(DartType type, String name) {
477 String parameterSource = utils.getParameterSource( 461 _EnclosingElementFinder finder = new _EnclosingElementFinder();
478 type, name, dartFileEditBuilder.librariesToImport); 462 finder.find(dartFileEditBuilder.unit, offset);
463 String parameterSource = _getParameterSource(
464 type, name, finder.enclosingClass, finder.enclosingExecutable);
479 write(parameterSource); 465 write(parameterSource);
480 } 466 }
481 467
482 @override 468 @override
483 bool writeType(DartType type, 469 bool writeType(DartType type,
484 {bool addSupertypeProposals: false, 470 {bool addSupertypeProposals: false,
485 String groupName, 471 String groupName,
486 bool required: false}) { 472 bool required: false}) {
487 if (type != null && !type.isDynamic) { 473 if (type != null && !type.isDynamic) {
488 String typeSource = 474 _EnclosingElementFinder finder = new _EnclosingElementFinder();
489 utils.getTypeSource(type, dartFileEditBuilder.librariesToImport); 475 finder.find(dartFileEditBuilder.unit, offset);
476 String typeSource = _getTypeSource(
477 type, finder.enclosingClass, finder.enclosingExecutable);
490 if (typeSource != 'dynamic') { 478 if (typeSource != 'dynamic') {
491 if (groupName != null) { 479 if (groupName != null) {
492 addLinkedEdit(groupName, (LinkedEditBuilder builder) { 480 addLinkedEdit(groupName, (LinkedEditBuilder builder) {
493 write(typeSource); 481 write(typeSource);
494 if (addSupertypeProposals) { 482 if (addSupertypeProposals) {
495 _addSuperTypeProposals(builder, type, new Set<DartType>()); 483 _addSuperTypeProposals(builder, type, new Set<DartType>());
496 } 484 }
497 }); 485 });
498 } else { 486 } else {
499 write(typeSource); 487 write(typeSource);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 ClassElement element = type.element as ClassElement; 552 ClassElement element = type.element as ClassElement;
565 builder.addSuggestion(LinkedEditSuggestionKind.TYPE, element.name); 553 builder.addSuggestion(LinkedEditSuggestionKind.TYPE, element.name);
566 _addSuperTypeProposals(builder, element.supertype, alreadyAdded); 554 _addSuperTypeProposals(builder, element.supertype, alreadyAdded);
567 for (InterfaceType interfaceType in element.interfaces) { 555 for (InterfaceType interfaceType in element.interfaces) {
568 _addSuperTypeProposals(builder, interfaceType, alreadyAdded); 556 _addSuperTypeProposals(builder, interfaceType, alreadyAdded);
569 } 557 }
570 } 558 }
571 } 559 }
572 560
573 /** 561 /**
562 * Return the import element used to import the given [element] into the given
563 * [library], or `null` if the element was not imported, such as when the
564 * element is declared in the same library.
565 */
566 ImportElement _getImportElement(Element element, LibraryElement library) {
567 for (ImportElement imp in library.imports) {
568 Map<String, Element> definedNames = getImportNamespace(imp);
569 if (definedNames.containsValue(element)) {
570 return imp;
571 }
572 }
573 return null;
574 }
575
576 /**
574 * Return a list containing the suggested names for a parameter with the given 577 * Return a list containing the suggested names for a parameter with the given
575 * [type] whose value in one location is computed by the given [expression]. 578 * [type] whose value in one location is computed by the given [expression].
576 * The list will not contain any names in the set of [excluded] names. The 579 * The list will not contain any names in the set of [excluded] names. The
577 * [index] is the index of the argument, used to create a name if no better 580 * [index] is the index of the argument, used to create a name if no better
578 * name could be created. The first name in the list will be the best name. 581 * name could be created. The first name in the list will be the best name.
579 */ 582 */
580 List<String> _getParameterNameSuggestions( 583 List<String> _getParameterNameSuggestions(
581 Set<String> usedNames, DartType type, Expression expression, int index) { 584 Set<String> usedNames, DartType type, Expression expression, int index) {
582 List<String> suggestions = 585 List<String> suggestions =
583 getVariableNameSuggestionsForExpression(type, expression, usedNames); 586 getVariableNameSuggestionsForExpression(type, expression, usedNames);
584 if (suggestions.length != 0) { 587 if (suggestions.length != 0) {
585 return suggestions; 588 return suggestions;
586 } 589 }
587 // TODO(brianwilkerson) Verify that the name below is not in the set of used names. 590 // TODO(brianwilkerson) Verify that the name below is not in the set of used names.
588 return <String>['param$index']; 591 return <String>['param$index'];
589 } 592 }
593
594 /**
595 * Return the source for the parameter with the given [type] and [name].
596 */
597 String _getParameterSource(DartType type, String name,
598 ClassElement enclosingClass, ExecutableElement enclosingExecutable) {
599 // no type
600 if (type == null || type.isDynamic) {
601 return name;
602 }
603 // function type
604 if (type is FunctionType && type.element.isSynthetic) {
605 FunctionType functionType = type;
606 StringBuffer sb = new StringBuffer();
607 // return type
608 DartType returnType = functionType.returnType;
609 if (returnType != null && !returnType.isDynamic) {
610 String returnTypeSource =
611 _getTypeSource(returnType, enclosingClass, enclosingExecutable);
612 sb.write(returnTypeSource);
613 sb.write(' ');
614 }
615 // parameter name
616 sb.write(name);
617 // parameters
618 sb.write('(');
619 List<ParameterElement> fParameters = functionType.parameters;
620 for (int i = 0; i < fParameters.length; i++) {
621 ParameterElement fParameter = fParameters[i];
622 if (i != 0) {
623 sb.write(", ");
624 }
625 sb.write(_getParameterSource(fParameter.type, fParameter.name,
626 enclosingClass, enclosingExecutable));
627 }
628 sb.write(')');
629 // done
630 return sb.toString();
631 }
632 // simple type
633 String typeSource =
634 _getTypeSource(type, enclosingClass, enclosingExecutable);
635 return '$typeSource $name';
636 }
637
638 /**
639 * Returns the source to reference [type] in this [CompilationUnit].
640 *
641 * Fills [librariesToImport] with [LibraryElement]s whose elements are
642 * used by the generated source, but not imported.
643 */
644 String _getTypeSource(DartType type, ClassElement enclosingClass,
645 ExecutableElement enclosingExecutable,
646 {StringBuffer parametersBuffer}) {
647 StringBuffer sb = new StringBuffer();
648 // type parameter
649 if (!_isTypeVisible(type, enclosingClass, enclosingExecutable)) {
650 return 'dynamic';
651 }
652 // just a Function, not FunctionTypeAliasElement
653 if (type is FunctionType && type.element is! FunctionTypeAliasElement) {
654 if (parametersBuffer == null) {
655 return "Function";
656 }
657 parametersBuffer.write('(');
658 for (ParameterElement parameter in type.parameters) {
659 String parameterType =
660 _getTypeSource(parameter.type, enclosingClass, enclosingExecutable);
661 if (parametersBuffer.length != 1) {
662 parametersBuffer.write(', ');
663 }
664 parametersBuffer.write(parameterType);
665 parametersBuffer.write(' ');
666 parametersBuffer.write(parameter.name);
667 }
668 parametersBuffer.write(')');
669 return _getTypeSource(
670 type.returnType, enclosingClass, enclosingExecutable);
671 }
672 // <Bottom>, Null
673 if (type.isBottom || type.isDartCoreNull) {
674 return 'dynamic';
675 }
676 // prepare element
677 Element element = type.element;
678 if (element == null) {
679 String source = type.toString();
680 source = source.replaceAll('<dynamic>', '');
681 source = source.replaceAll('<dynamic, dynamic>', '');
682 return source;
683 }
684 // check if imported
685 LibraryElement definingLibrary = element.library;
686 LibraryElement importingLibrary = dartFileEditBuilder.unit.element.library;
687 if (definingLibrary != null && definingLibrary != importingLibrary) {
688 // no source, if private
689 if (element.isPrivate) {
690 return null;
691 }
692 // ensure import
693 ImportElement importElement =
694 _getImportElement(element, importingLibrary);
695 if (importElement != null) {
696 if (importElement.prefix != null) {
697 sb.write(importElement.prefix.displayName);
698 sb.write(".");
699 }
700 } else {
701 importLibrary(definingLibrary.source);
702 }
703 }
704 // append simple name
705 String name = element.displayName;
706 sb.write(name);
707 // may be type arguments
708 if (type is ParameterizedType) {
709 List<DartType> arguments = type.typeArguments;
710 // check if has arguments
711 bool hasArguments = false;
712 bool allArgumentsVisible = true;
713 for (DartType argument in arguments) {
714 hasArguments = hasArguments || !argument.isDynamic;
715 allArgumentsVisible = allArgumentsVisible &&
716 _isTypeVisible(argument, enclosingClass, enclosingExecutable);
717 }
718 // append type arguments
719 if (hasArguments && allArgumentsVisible) {
720 sb.write("<");
721 for (int i = 0; i < arguments.length; i++) {
722 DartType argument = arguments[i];
723 if (i != 0) {
724 sb.write(", ");
725 }
726 String argumentSrc =
727 _getTypeSource(argument, enclosingClass, enclosingExecutable);
728 if (argumentSrc != null) {
729 sb.write(argumentSrc);
730 } else {
731 return null;
732 }
733 }
734 sb.write(">");
735 }
736 }
737 // done
738 return sb.toString();
739 }
740
741 /**
742 * Checks if [type] is visible in either the [enclosingExecutable] or
743 * [enclosingClass].
744 */
745 bool _isTypeVisible(DartType type, ClassElement enclosingClass,
746 ExecutableElement enclosingExecutable) {
747 if (type is TypeParameterType) {
748 TypeParameterElement parameterElement = type.element;
749 Element parameterParent = parameterElement.enclosingElement;
750 // TODO(brianwilkerson) This needs to compare the parameterParent with
751 // each of the parents of the enclosingElement. (That means that we only
752 // need the most closely enclosing element.)
753 return identical(parameterParent, enclosingExecutable) ||
754 identical(parameterParent, enclosingClass);
755 }
756 return true;
757 }
590 } 758 }
591 759
592 /** 760 /**
593 * A [FileEditBuilder] used to build edits for Dart files. 761 * A [FileEditBuilder] used to build edits for Dart files.
594 */ 762 */
595 class DartFileEditBuilderImpl extends FileEditBuilderImpl 763 class DartFileEditBuilderImpl extends FileEditBuilderImpl
596 implements DartFileEditBuilder { 764 implements DartFileEditBuilder {
597 /** 765 /**
598 * The compilation unit to which the code will be added. 766 * The compilation unit to which the code will be added.
599 */ 767 */
600 CompilationUnit unit; 768 CompilationUnit unit;
601 769
602 /** 770 /**
603 * A utility class used to help build the source code.
604 */
605 CorrectionUtils utils;
606
607 /**
608 * A set containing the sources of the libraries that need to be imported in 771 * A set containing the sources of the libraries that need to be imported in
609 * order to make visible the names used in generated code. 772 * order to make visible the names used in generated code.
610 */ 773 */
611 Set<Source> librariesToImport = new Set<Source>(); 774 Set<Source> librariesToImport = new Set<Source>();
612 775
613 /** 776 /**
777 * The content of the file being edited.
778 */
779 String _content;
780
781 /**
614 * Initialize a newly created builder to build a source file edit within the 782 * Initialize a newly created builder to build a source file edit within the
615 * change being built by the given [changeBuilder]. The file being edited has 783 * change being built by the given [changeBuilder]. The file being edited has
616 * the given [source] and [timeStamp], and the given fully resolved [unit]. 784 * the given [source] and [timeStamp], and the given fully resolved [unit].
617 */ 785 */
618 DartFileEditBuilderImpl(DartChangeBuilderImpl changeBuilder, String path, 786 DartFileEditBuilderImpl(DartChangeBuilderImpl changeBuilder, String path,
619 int timeStamp, this.unit) 787 int timeStamp, this.unit)
620 : super(changeBuilder, path, timeStamp) { 788 : super(changeBuilder, path, timeStamp);
621 utils = new CorrectionUtils(unit);
622 }
623 789
624 @override 790 @override
625 void convertFunctionFromSyncToAsync( 791 void convertFunctionFromSyncToAsync(
626 FunctionBody body, TypeProvider typeProvider) { 792 FunctionBody body, TypeProvider typeProvider) {
627 if (body == null && body.keyword != null) { 793 if (body == null && body.keyword != null) {
628 throw new ArgumentError( 794 throw new ArgumentError(
629 'The function must have a synchronous, non-generator body.'); 795 'The function must have a synchronous, non-generator body.');
630 } 796 }
631 addInsertion(body.offset, (EditBuilder builder) { 797 addInsertion(body.offset, (EditBuilder builder) {
632 builder.write('async '); 798 builder.write('async ');
633 }); 799 });
634 _replaceReturnTypeWithFuture(body, typeProvider); 800 _replaceReturnTypeWithFuture(body, typeProvider);
635 } 801 }
636 802
637 @override 803 @override
638 DartEditBuilderImpl createEditBuilder(int offset, int length) { 804 DartEditBuilderImpl createEditBuilder(int offset, int length) {
639 return new DartEditBuilderImpl(this, offset, length); 805 return new DartEditBuilderImpl(this, offset, length);
640 } 806 }
641 807
642 @override 808 @override
643 void finalize() { 809 void finalize() {
644 addLibraryImports( 810 addLibraryImports(
645 changeBuilder.sourceChange, unit.element.library, librariesToImport); 811 changeBuilder.sourceChange, unit.element.library, librariesToImport);
646 } 812 }
647 813
814 /**
815 * Return the content of the file being edited.
816 */
817 String getContent() {
818 if (_content == null) {
819 CompilationUnitElement unitElement = unit.element;
820 AnalysisContext context = unitElement.context;
821 if (context == null) {
822 throw new CancelCorrectionException();
823 }
824 _content = context.getContents(unitElement.source).data;
825 }
826 return _content;
827 }
828
648 @override 829 @override
649 void importLibraries(Iterable<Source> libraries) { 830 void importLibraries(Iterable<Source> libraries) {
650 librariesToImport.addAll(libraries); 831 librariesToImport.addAll(libraries);
651 } 832 }
652 833
653 @override 834 @override
654 void replaceTypeWithFuture( 835 void replaceTypeWithFuture(
655 TypeAnnotation typeAnnotation, TypeProvider typeProvider) { 836 TypeAnnotation typeAnnotation, TypeProvider typeProvider) {
656 InterfaceType futureType = typeProvider.futureType; 837 InterfaceType futureType = typeProvider.futureType;
657 // 838 //
658 // Check whether the type needs to be replaced. 839 // Check whether the type needs to be replaced.
659 // 840 //
660 DartType type = typeAnnotation?.type; 841 DartType type = typeAnnotation?.type;
661 if (type == null || 842 if (type == null ||
662 type.isDynamic || 843 type.isDynamic ||
663 type is InterfaceType && type.element == futureType.element) { 844 type is InterfaceType && type.element == futureType.element) {
664 return; 845 return;
665 } 846 }
847 futureType = futureType.instantiate(<DartType>[type]);
666 // prepare code for the types 848 // prepare code for the types
667 String futureTypeCode = utils.getTypeSource(futureType, librariesToImport);
668 String nodeCode = utils.getNodeText(typeAnnotation);
669 // wrap the existing type with Future
670 String returnTypeCode =
671 nodeCode == 'void' ? futureTypeCode : '$futureTypeCode<$nodeCode>';
672 addReplacement(rangeNode(typeAnnotation), (EditBuilder builder) { 849 addReplacement(rangeNode(typeAnnotation), (EditBuilder builder) {
673 builder.write(returnTypeCode); 850 if (!(builder as DartEditBuilder).writeType(futureType)) {
851 builder.write('void');
852 }
674 }); 853 });
675 } 854 }
676 855
677 /** 856 /**
857 * Returns the text of the given [AstNode] in the unit.
858 */
859 String _getNodeText(AstNode node) {
860 return _getText(node.offset, node.length);
861 }
862
863 /**
864 * Returns the text of the given range in the unit.
865 */
866 String _getText(int offset, int length) {
867 return getContent().substring(offset, offset + length);
868 }
869
870 /**
678 * Create an edit to replace the return type of the innermost function 871 * Create an edit to replace the return type of the innermost function
679 * containing the given [node] with the type `Future`. The [typeProvider] is 872 * containing the given [node] with the type `Future`. The [typeProvider] is
680 * used to check the current return type, because if it is already `Future` no 873 * used to check the current return type, because if it is already `Future` no
681 * edit will be added. 874 * edit will be added.
682 */ 875 */
683 void _replaceReturnTypeWithFuture(AstNode node, TypeProvider typeProvider) { 876 void _replaceReturnTypeWithFuture(AstNode node, TypeProvider typeProvider) {
684 while (node != null) { 877 while (node != null) {
685 node = node.parent; 878 node = node.parent;
686 if (node is FunctionDeclaration) { 879 if (node is FunctionDeclaration) {
687 replaceTypeWithFuture(node.returnType, typeProvider); 880 replaceTypeWithFuture(node.returnType, typeProvider);
(...skipping 30 matching lines...) Expand all
718 void _addSuperTypesAsSuggestions(DartType type, Set<DartType> alreadyAdded) { 911 void _addSuperTypesAsSuggestions(DartType type, Set<DartType> alreadyAdded) {
719 if (type is InterfaceType && alreadyAdded.add(type)) { 912 if (type is InterfaceType && alreadyAdded.add(type)) {
720 addSuggestion(LinkedEditSuggestionKind.TYPE, type.displayName); 913 addSuggestion(LinkedEditSuggestionKind.TYPE, type.displayName);
721 _addSuperTypesAsSuggestions(type.superclass, alreadyAdded); 914 _addSuperTypesAsSuggestions(type.superclass, alreadyAdded);
722 for (InterfaceType interfaceType in type.interfaces) { 915 for (InterfaceType interfaceType in type.interfaces) {
723 _addSuperTypesAsSuggestions(interfaceType, alreadyAdded); 916 _addSuperTypesAsSuggestions(interfaceType, alreadyAdded);
724 } 917 }
725 } 918 }
726 } 919 }
727 } 920 }
921
922 class _EnclosingElementFinder {
923 ClassElement enclosingClass;
924 ExecutableElement enclosingExecutable;
925
926 _EnclosingElementFinder();
927
928 void find(AstNode target, int offset) {
929 AstNode node = new NodeLocator2(offset).searchWithin(target);
930 while (node != null) {
931 if (node is ClassDeclaration) {
932 enclosingClass = node.element;
933 } else if (node is ConstructorDeclaration) {
934 enclosingExecutable = node.element;
935 } else if (node is MethodDeclaration) {
936 enclosingExecutable = node.element;
937 } else if (node is FunctionDeclaration) {
938 enclosingExecutable = node.element;
939 }
940 node = node.parent;
941 }
942 }
943 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/provisional/edit/utilities/change_builder_dart.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698