Future complete()

in lib/completion.dart [25:178]


  Future<CompletionResult> complete(
    Editor editor, {
    bool onlyShowFixes = false,
  }) {
    // Cancel any open completion request.
    _lastCompleter?.operation.cancel();

    final offset = editor.document.indexFromPos(editor.document.cursor);

    final request = ds.SourceRequest()
      ..source = editor.document.value
      ..offset = offset;

    final completer = CancelableCompleter<CompletionResult>();
    _lastCompleter = completer;

    if (onlyShowFixes) {
      final completions = <Completion>[];
      final fixesFuture =
          servicesApi.fixes(request).then((ds.FixesResponse response) {
        for (final problemFix in response.fixes) {
          for (final fix in problemFix.fixes) {
            final fixes = fix.edits.map((edit) {
              return SourceEdit(edit.length, edit.offset, edit.replacement);
            }).toList();

            completions.add(Completion(
              '',
              displayString: fix.message,
              type: 'type-quick_fix',
              quickFixes: fixes,
            ));
          }
        }
      });
      final assistsFuture =
          servicesApi.assists(request).then((ds.AssistsResponse response) {
        for (final assist in response.assists) {
          final sourceEdits = assist.edits
              .map((edit) =>
                  SourceEdit(edit.length, edit.offset, edit.replacement))
              .toList();

          int? absoluteCursorPosition;

          // TODO(redbrogdon): Find a way to properly use these linked edit
          // groups via selections and multiple cursors.
          if (assist.linkedEditGroups.isNotEmpty) {
            absoluteCursorPosition =
                assist.linkedEditGroups.first.positions.first;
          }

          // If a specific offset is provided, prefer it to the one calculated
          // from the linked edit groups.
          if (assist.hasSelectionOffset()) {
            absoluteCursorPosition = assist.selectionOffset;
          }

          final completion = Completion(
            '',
            displayString: assist.message,
            type: 'type-quick_fix',
            quickFixes: sourceEdits,
            absoluteCursorPosition: absoluteCursorPosition,
          );

          completions.add(completion);
        }
      });

      Future.wait([fixesFuture, assistsFuture]).then((_) {
        completer.complete(CompletionResult(completions,
            replaceOffset: offset, replaceLength: 0));
      });
    } else {
      servicesApi.complete(request).then((ds.CompleteResponse response) {
        if (completer.isCanceled) return;

        final replaceOffset = response.replacementOffset;
        final replaceLength = response.replacementLength;

        final responses = response.completions.map((completion) {
          return AnalysisCompletion(replaceOffset, replaceLength, completion);
        });

        final completions = responses.map((completion) {
          // TODO: Move to using a LabelProvider; decouple the data and rendering.
          var displayString = completion.isMethod
              ? '${completion.text}${completion.parameters}'
              : completion.text;
          if (completion.isMethod && completion.returnType != null) {
            displayString += ' → ${completion.returnType}';
          }

          var text = completion.text;

          if (completion.isMethod) {
            text += '()';
          }

          if (completion.isConstructor) {
            displayString += '()';
          }

          final deprecatedClass = completion.isDeprecated ? ' deprecated' : '';

          if (completion.type == null) {
            return Completion(
              text,
              displayString: displayString,
              type: deprecatedClass,
            );
          } else {
            int? cursorPos;

            if (completion.isMethod && completion.parameterCount! > 0) {
              cursorPos = text.indexOf('(') + 1;
            }

            if (completion.selectionOffset != 0) {
              cursorPos = completion.selectionOffset;
            }

            return Completion(
              text,
              displayString: displayString,
              type: 'type-${completion.type!.toLowerCase()}$deprecatedClass',
              cursorOffset: cursorPos,
            );
          }
        }).toList();

        // Removes duplicates when a completion is both a getter and a setter.
        for (final completion in completions) {
          for (final other in completions) {
            if (completion.isSetterAndMatchesGetter(other)) {
              completions.removeWhere((c) => completion == c);
              other.type = 'type-getter_and_setter';
            }
          }
        }

        completer.complete(CompletionResult(
          completions,
          replaceOffset: replaceOffset,
          replaceLength: replaceLength,
        ));
      }).catchError((e) {
        completer.completeError(e as Object);
      });
    }

    return completer.operation.value;
  }