Skip to content

Commit

Permalink
[analysis_server] Add a user setting to control verbosity of dartdocs…
Browse files Browse the repository at this point in the history
… in LSP hovers and related responses

Fixes Dart-Code/Dart-Code#4119.

Change-Id: I26aa074f35b87ced1e09073f534451248c633402
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/266741
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Brian Wilkerson <[email protected]>
  • Loading branch information
DanTup authored and Commit Queue committed Oct 31, 2022
1 parent 925268b commit 09c1722
Show file tree
Hide file tree
Showing 13 changed files with 450 additions and 46 deletions.
39 changes: 37 additions & 2 deletions pkg/analysis_server/lib/src/computer/computer_hover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ class DartUnitHoverComputer {
final DartdocDirectiveInfo _dartdocInfo;
final CompilationUnit _unit;
final int _offset;
final DocumentationPreference documentationPreference;

DartUnitHoverComputer(this._dartdocInfo, this._unit, this._offset);
DartUnitHoverComputer(
this._dartdocInfo,
this._unit,
this._offset, {
this.documentationPreference = DocumentationPreference.full,
});

/// Returns the computed hover, maybe `null`.
HoverInformation? compute() {
Expand Down Expand Up @@ -141,7 +147,8 @@ class DartUnitHoverComputer {
}
}
// documentation
hover.dartdoc = computeDocumentation(_dartdocInfo, element)?.full;
hover.dartdoc = computePreferredDocumentation(
_dartdocInfo, element, documentationPreference);
}
// parameter
if (node is Expression) {
Expand Down Expand Up @@ -253,6 +260,26 @@ class DartUnitHoverComputer {
return result;
}

/// Compute documentation for [element] and return either the summary or full
/// docs (or `null`) depending on `preference`.
static String? computePreferredDocumentation(
DartdocDirectiveInfo dartdocInfo,
Element element,
DocumentationPreference preference,
) {
if (preference == DocumentationPreference.none) {
return null;
}

final doc = computeDocumentation(
dartdocInfo,
element,
includeSummary: preference == DocumentationPreference.summary,
);

return doc is DocumentationWithSummary ? doc.summary : doc?.full;
}

static DartType? _getTypeOfDeclarationOrReference(Expression node) {
if (node is SimpleIdentifier) {
var element = node.staticElement;
Expand All @@ -269,3 +296,11 @@ class DartUnitHoverComputer {
return node.staticType;
}
}

/// The type of documentation the user prefers to see in hovers and other
/// related displays in their editor.
enum DocumentationPreference {
none,
summary,
full,
}
17 changes: 11 additions & 6 deletions pkg/analysis_server/lib/src/computer/computer_signature.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
Expand All @@ -18,8 +18,14 @@ class DartUnitSignatureComputer {
final AstNode? _node;
late ArgumentList _argumentList;
final bool _isNonNullableByDefault;
DartUnitSignatureComputer(this._dartdocInfo, CompilationUnit unit, int offset)
: _node = NodeLocator(offset).searchWithin(unit),
final DocumentationPreference documentationPreference;

DartUnitSignatureComputer(
this._dartdocInfo,
CompilationUnit unit,
int offset, {
this.documentationPreference = DocumentationPreference.full,
}) : _node = NodeLocator(offset).searchWithin(unit),
_isNonNullableByDefault = unit.isNonNullableByDefault;

/// The [ArgumentList] node located by [compute].
Expand Down Expand Up @@ -59,9 +65,8 @@ class DartUnitSignatureComputer {
execElement.parameters.map((p) => _convertParam(p)).toList();

return AnalysisGetSignatureResult(name, parameters,
dartdoc: DartUnitHoverComputer.computeDocumentation(
_dartdocInfo, execElement)
?.full);
dartdoc: DartUnitHoverComputer.computePreferredDocumentation(
_dartdocInfo, execElement, documentationPreference));
}

ParameterInfo _convertParam(ParameterElement param) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ class DartTypeArgumentsSignatureComputer {
final Set<lsp.MarkupKind>? preferredFormats;
late TypeArgumentList _argumentList;
final bool _isNonNullableByDefault;
final DocumentationPreference documentationPreference;

DartTypeArgumentsSignatureComputer(
this._dartdocInfo,
CompilationUnit unit,
int offset,
this.preferredFormats,
) : _node = NodeLocator(offset).searchWithin(unit),
this.preferredFormats, {
this.documentationPreference = DocumentationPreference.full,
}) : _node = NodeLocator(offset).searchWithin(unit),
_isNonNullableByDefault = unit.isNonNullableByDefault;

/// The [TypeArgumentList] node located by [compute].
Expand Down Expand Up @@ -57,8 +60,8 @@ class DartTypeArgumentsSignatureComputer {

final label =
element.getDisplayString(withNullability: _isNonNullableByDefault);
final documentation =
DartUnitHoverComputer.computeDocumentation(_dartdocInfo, element)?.full;
final documentation = DartUnitHoverComputer.computePreferredDocumentation(
_dartdocInfo, element, documentationPreference);

return _toSignatureHelp(
label,
Expand Down
18 changes: 18 additions & 0 deletions pkg/analysis_server/lib/src/lsp/client_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;

Expand Down Expand Up @@ -141,6 +142,23 @@ class LspGlobalClientConfiguration extends LspResourceClientConfiguration {
bool get experimentalNewRefactors =>
_settings['experimentalNewRefactors'] as bool? ?? false;

/// The users preferred kind of documentation for Hovers, Code Completion and
/// other related panels in the UI.
///
/// If the user has not expressed a preference, defaults to
/// [DocumentationPreference.full].
DocumentationPreference get preferredDocumentation {
final value = _settings['documentation'];
switch (value) {
case 'none':
return DocumentationPreference.none;
case 'summary':
return DocumentationPreference.summary;
default:
return DocumentationPreference.full;
}
}

/// A preview flag for enabling commit characters for completions.
///
/// This is a temporary setting to allow this feature to be tested without
Expand Down
56 changes: 33 additions & 23 deletions pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:math' as math;

import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
Expand Down Expand Up @@ -478,8 +479,10 @@ class CompletionHandler extends MessageHandler<CompletionParams, CompletionList>
completeFunctionCalls: completeFunctionCalls,
resolutionData: resolutionInfo,
// Exclude docs if we will be providing them via
// `completionItem/resolve`.
includeDocs: resolutionInfo == null,
// `completionItem/resolve`, otherwise use users preference.
includeDocumentation: resolutionInfo != null
? DocumentationPreference.none
: server.clientConfiguration.global.preferredDocumentation,
);
}

Expand Down Expand Up @@ -576,27 +579,32 @@ class CompletionHandler extends MessageHandler<CompletionParams, CompletionList>
final completionItems = suggestions.suggestions
.where((item) =>
fuzzyMatcher.score(item.displayText ?? item.completion) > 0)
.map(
(item) => toCompletionItem(
capabilities,
lineInfo,
item,
replacementRange: replacementRange,
insertionRange: insertionRange,
commitCharactersEnabled: false,
completeFunctionCalls: false,
// Add on any completion-kind-specific resolution data that will be
// used during resolve() calls to provide additional information.
resolutionData: item.kind == CompletionSuggestionKind.PACKAGE_NAME
? PubPackageCompletionItemResolutionInfo(
// The completion for package names may contain a trailing
// ': ' for convenience, so if it's there, trim it off.
packageName: item.completion.split(':').first,
)
: null,
),
)
.toList();
.map((item) {
final resolutionInfo = item.kind == CompletionSuggestionKind.PACKAGE_NAME
? PubPackageCompletionItemResolutionInfo(
// The completion for package names may contain a trailing
// ': ' for convenience, so if it's there, trim it off.
packageName: item.completion.split(':').first,
)
: null;
return toCompletionItem(
capabilities,
lineInfo,
item,
replacementRange: replacementRange,
insertionRange: insertionRange,
commitCharactersEnabled: false,
completeFunctionCalls: false,
// Exclude docs if we could provide them via
// `completionItem/resolve`, otherwise use users preference.
includeDocumentation: resolutionInfo != null
? DocumentationPreference.none
: server.clientConfiguration.global.preferredDocumentation,
// Add on any completion-kind-specific resolution data that will be
// used during resolve() calls to provide additional information.
resolutionData: resolutionInfo,
);
}).toList();
return success(
_CompletionResults.unranked(completionItems, isIncomplete: false),
);
Expand Down Expand Up @@ -649,6 +657,8 @@ class CompletionHandler extends MessageHandler<CompletionParams, CompletionList>
item,
replacementRange: replacementRange,
insertionRange: insertionRange,
includeDocumentation:
server.clientConfiguration.global.preferredDocumentation,
// Plugins cannot currently contribute commit characters and we should
// not assume that the Dart ones would be correct for all of their
// completions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ class CompletionResolveHandler
if (element != null) {
final formats = clientCapabilities.completionDocumentationFormats;
final dartDocInfo = server.getDartdocDirectiveInfoForSession(session);
final dartDocData =
DartUnitHoverComputer.computeDocumentation(dartDocInfo, element);
final dartDoc = dartDocData?.full;
final dartDoc = DartUnitHoverComputer.computePreferredDocumentation(
dartDocInfo,
element,
server.clientConfiguration.global.preferredDocumentation);
// `dartDoc` can be both null or empty.
documentation = dartDoc != null && dartDoc.isNotEmpty
? asMarkupContentOrString(formats, dartDoc)
Expand Down
7 changes: 6 additions & 1 deletion pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,12 @@ class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover?> {
ErrorOr<Hover?> _getHover(ResolvedUnitResult unit, int offset) {
final compilationUnit = unit.unit;
final computer = DartUnitHoverComputer(
server.getDartdocDirectiveInfoFor(unit), compilationUnit, offset);
server.getDartdocDirectiveInfoFor(unit),
compilationUnit,
offset,
documentationPreference:
server.clientConfiguration.global.preferredDocumentation,
);
final hover = computer.compute();
return success(toHover(unit.lineInfo, hover));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ class SignatureHelpHandler
return success(typeArgsSignature);
}

final computer =
DartUnitSignatureComputer(dartDocInfo, unit.result.unit, offset);
final computer = DartUnitSignatureComputer(
dartDocInfo,
unit.result.unit,
offset,
documentationPreference:
server.clientConfiguration.global.preferredDocumentation,
);
if (!computer.offsetIsValid) {
return success(null); // No error, just no valid hover.
}
Expand Down Expand Up @@ -102,8 +107,10 @@ class SignatureHelpHandler
bool autoTriggered,
Set<MarkupKind>? formats,
) {
final typeArgsComputer =
DartTypeArgumentsSignatureComputer(dartDocInfo, unit, offset, formats);
final typeArgsComputer = DartTypeArgumentsSignatureComputer(
dartDocInfo, unit, offset, formats,
documentationPreference:
server.clientConfiguration.global.preferredDocumentation);
if (!typeArgsComputer.offsetIsValid) {
return null;
}
Expand Down
12 changes: 9 additions & 3 deletions pkg/analysis_server/lib/src/lsp/mapping.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:io';
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp;
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
import 'package:analysis_server/src/lsp/constants.dart';
Expand Down Expand Up @@ -874,7 +875,7 @@ lsp.CompletionItem toCompletionItem(
bool hasDefaultTextMode = false,
required Range replacementRange,
required Range insertionRange,
bool includeDocs = true,
required DocumentationPreference includeDocumentation,
required bool commitCharactersEnabled,
required bool completeFunctionCalls,
CompletionItemResolutionInfo? resolutionData,
Expand Down Expand Up @@ -944,7 +945,12 @@ lsp.CompletionItem toCompletionItem(
final insertTextFormat = insertTextInfo.last;
final isMultilineCompletion = insertText.contains('\n');

var cleanedDoc = cleanDartdoc(suggestion.docComplete);
final rawDoc = includeDocumentation == DocumentationPreference.full
? suggestion.docComplete
: includeDocumentation == DocumentationPreference.summary
? suggestion.docSummary
: null;
var cleanedDoc = cleanDartdoc(rawDoc);
var detail = getCompletionDetail(suggestion, completionKind,
supportsCompletionDeprecatedFlag || supportsDeprecatedTag);

Expand All @@ -971,7 +977,7 @@ lsp.CompletionItem toCompletionItem(
]),
data: resolutionData,
detail: detail,
documentation: cleanedDoc != null && includeDocs
documentation: cleanedDoc != null
? asMarkupContentOrString(formats, cleanedDoc)
: null,
deprecated: supportsCompletionDeprecatedFlag && suggestion.isDeprecated
Expand Down
Loading

0 comments on commit 09c1722

Please sign in to comment.