Skip to content

Commit 83aaca0

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Split documentation out of hover computer
The hover computer had some logic in it that was reused elsewhere (like completion and signature help) and a TODO to move it out. While trying to migrate signature help I ended up trying to migrate the whole hover class which then led to other classes and got big. Hopefully splitting these up will make it easier to migrate them separately. Change-Id: I3b9a78bf69620ae2deaec41b31979fbf8dc918c0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/390701 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 18b8904 commit 83aaca0

File tree

10 files changed

+140
-131
lines changed

10 files changed

+140
-131
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:analysis_server/src/computer/computer_overrides.dart';
6+
import 'package:analyzer/dart/element/element.dart';
7+
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
8+
9+
/// Computes documentation for an [Element].
10+
class DartDocumentationComputer {
11+
final DartdocDirectiveInfo dartdocInfo;
12+
13+
DartDocumentationComputer(this.dartdocInfo);
14+
15+
Documentation? compute(
16+
Element elementBeingDocumented, {
17+
bool includeSummary = false,
18+
}) {
19+
Element? element = elementBeingDocumented;
20+
if (element is FieldFormalParameterElement) {
21+
element = element.field;
22+
}
23+
if (element is ParameterElement) {
24+
element = element.enclosingElement3;
25+
}
26+
if (element == null) {
27+
// This can happen when the code is invalid, such as having a field formal
28+
// parameter for a field that does not exist.
29+
return null;
30+
}
31+
32+
Element? documentedElement;
33+
Element? documentedGetter;
34+
35+
// Look for documentation comments of overridden members
36+
var overridden = findOverriddenElements(element);
37+
var candidates = [
38+
element,
39+
...overridden.superElements,
40+
...overridden.interfaceElements,
41+
if (element case PropertyAccessorElement(variable2: var variable?))
42+
variable
43+
];
44+
for (var candidate in candidates) {
45+
if (candidate.documentationComment != null) {
46+
documentedElement = candidate;
47+
break;
48+
}
49+
if (documentedGetter == null &&
50+
candidate is PropertyAccessorElement &&
51+
candidate.isSetter) {
52+
var getter = candidate.correspondingGetter;
53+
if (getter != null && getter.documentationComment != null) {
54+
documentedGetter = getter;
55+
}
56+
}
57+
}
58+
59+
// Use documentation of a corresponding getter if setters don't have it
60+
documentedElement ??= documentedGetter;
61+
if (documentedElement == null) {
62+
return null;
63+
}
64+
65+
var rawDoc = documentedElement.documentationComment;
66+
if (rawDoc == null) {
67+
return null;
68+
}
69+
var result =
70+
dartdocInfo.processDartdoc(rawDoc, includeSummary: includeSummary);
71+
72+
var documentedElementClass = documentedElement.enclosingElement3;
73+
if (documentedElementClass != null &&
74+
documentedElementClass != element.enclosingElement3) {
75+
var documentedClass = documentedElementClass.displayName;
76+
result.full = '${result.full}\n\nCopied from `$documentedClass`.';
77+
}
78+
79+
return result;
80+
}
81+
82+
/// Compute documentation for [element] and return either the summary or full
83+
/// docs (or `null`) depending on `preference`.
84+
String? computePreferred(
85+
Element element, DocumentationPreference preference) {
86+
if (preference == DocumentationPreference.none) {
87+
return null;
88+
}
89+
90+
var doc = compute(
91+
element,
92+
includeSummary: preference == DocumentationPreference.summary,
93+
);
94+
95+
return doc is DocumentationWithSummary ? doc.summary : doc?.full;
96+
}
97+
}
98+
99+
/// The type of documentation the user prefers to see in hovers and other
100+
/// related displays in their editor.
101+
enum DocumentationPreference {
102+
none,
103+
summary,
104+
full,
105+
}

pkg/analysis_server/lib/src/computer/computer_hover.dart

Lines changed: 6 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import 'package:analysis_server/protocol/protocol_generated.dart'
66
show HoverInformation;
7-
import 'package:analysis_server/src/computer/computer_overrides.dart';
7+
import 'package:analysis_server/src/computer/computer_documentation.dart';
88
import 'package:analyzer/dart/ast/ast.dart';
99
import 'package:analyzer/dart/ast/syntactic_entity.dart';
1010
import 'package:analyzer/dart/element/element.dart';
@@ -21,17 +21,17 @@ typedef _OffsetLength = ({int offset, int length});
2121
/// A computer for the hover at the specified offset of a Dart
2222
/// [CompilationUnit].
2323
class DartUnitHoverComputer {
24-
final DartdocDirectiveInfo _dartdocInfo;
2524
final CompilationUnit _unit;
2625
final int _offset;
2726
final DocumentationPreference documentationPreference;
27+
final DartDocumentationComputer _documentationComputer;
2828

2929
DartUnitHoverComputer(
30-
this._dartdocInfo,
30+
DartdocDirectiveInfo dartdocInfo,
3131
this._unit,
3232
this._offset, {
3333
this.documentationPreference = DocumentationPreference.full,
34-
});
34+
}) : _documentationComputer = DartDocumentationComputer(dartdocInfo);
3535

3636
/// Returns the computed hover, maybe `null`.
3737
HoverInformation? compute() {
@@ -83,8 +83,8 @@ class DartUnitHoverComputer {
8383
hover.containingLibraryPath = libraryInfo?.libraryPath;
8484
}
8585
// documentation
86-
hover.dartdoc = computePreferredDocumentation(
87-
_dartdocInfo, element, documentationPreference);
86+
hover.dartdoc = _documentationComputer.computePreferred(
87+
element, documentationPreference);
8888
}
8989
// parameter
9090
hover.parameter = _parameterDisplayString(node);
@@ -272,94 +272,6 @@ class DartUnitHoverComputer {
272272
element.isSynthetic);
273273
}
274274

275-
static Documentation? computeDocumentation(
276-
DartdocDirectiveInfo dartdocInfo, Element elementBeingDocumented,
277-
{bool includeSummary = false}) {
278-
// TODO(dantup): We're reusing this in parameter information - move it
279-
// somewhere shared?
280-
Element? element = elementBeingDocumented;
281-
if (element is FieldFormalParameterElement) {
282-
element = element.field;
283-
}
284-
if (element is ParameterElement) {
285-
element = element.enclosingElement3;
286-
}
287-
if (element == null) {
288-
// This can happen when the code is invalid, such as having a field formal
289-
// parameter for a field that does not exist.
290-
return null;
291-
}
292-
293-
Element? documentedElement;
294-
Element? documentedGetter;
295-
296-
// Look for documentation comments of overridden members
297-
var overridden = findOverriddenElements(element);
298-
var candidates = [
299-
element,
300-
...overridden.superElements,
301-
...overridden.interfaceElements,
302-
if (element case PropertyAccessorElement(variable2: var variable?))
303-
variable
304-
];
305-
for (var candidate in candidates) {
306-
if (candidate.documentationComment != null) {
307-
documentedElement = candidate;
308-
break;
309-
}
310-
if (documentedGetter == null &&
311-
candidate is PropertyAccessorElement &&
312-
candidate.isSetter) {
313-
var getter = candidate.correspondingGetter;
314-
if (getter != null && getter.documentationComment != null) {
315-
documentedGetter = getter;
316-
}
317-
}
318-
}
319-
320-
// Use documentation of a corresponding getter if setters don't have it
321-
documentedElement ??= documentedGetter;
322-
if (documentedElement == null) {
323-
return null;
324-
}
325-
326-
var rawDoc = documentedElement.documentationComment;
327-
if (rawDoc == null) {
328-
return null;
329-
}
330-
var result =
331-
dartdocInfo.processDartdoc(rawDoc, includeSummary: includeSummary);
332-
333-
var documentedElementClass = documentedElement.enclosingElement3;
334-
if (documentedElementClass != null &&
335-
documentedElementClass != element.enclosingElement3) {
336-
var documentedClass = documentedElementClass.displayName;
337-
result.full = '${result.full}\n\nCopied from `$documentedClass`.';
338-
}
339-
340-
return result;
341-
}
342-
343-
/// Compute documentation for [element] and return either the summary or full
344-
/// docs (or `null`) depending on `preference`.
345-
static String? computePreferredDocumentation(
346-
DartdocDirectiveInfo dartdocInfo,
347-
Element element,
348-
DocumentationPreference preference,
349-
) {
350-
if (preference == DocumentationPreference.none) {
351-
return null;
352-
}
353-
354-
var doc = computeDocumentation(
355-
dartdocInfo,
356-
element,
357-
includeSummary: preference == DocumentationPreference.summary,
358-
);
359-
360-
return doc is DocumentationWithSummary ? doc.summary : doc?.full;
361-
}
362-
363275
static DartType? _getTypeOfDeclarationOrReference(Expression node) {
364276
if (node is SimpleIdentifier) {
365277
var element = node.staticElement;
@@ -392,11 +304,3 @@ class DartUnitHoverComputer {
392304
return node.staticType;
393305
}
394306
}
395-
396-
/// The type of documentation the user prefers to see in hovers and other
397-
/// related displays in their editor.
398-
enum DocumentationPreference {
399-
none,
400-
summary,
401-
full,
402-
}

pkg/analysis_server/lib/src/computer/computer_signature.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analysis_server/src/computer/computer_hover.dart';
5+
import 'package:analysis_server/src/computer/computer_documentation.dart';
66
import 'package:analysis_server/src/protocol_server.dart' hide Element;
77
import 'package:analysis_server/src/utilities/extensions/ast.dart';
88
import 'package:analyzer/dart/ast/ast.dart';
@@ -15,17 +15,18 @@ import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
1515
/// A computer for the signature at the specified offset of a Dart
1616
/// [CompilationUnit].
1717
class DartUnitSignatureComputer {
18-
final DartdocDirectiveInfo _dartdocInfo;
1918
final AstNode? _node;
2019
late ArgumentList _argumentList;
2120
final DocumentationPreference documentationPreference;
21+
final DartDocumentationComputer _documentationComputer;
2222

2323
DartUnitSignatureComputer(
24-
this._dartdocInfo,
24+
DartdocDirectiveInfo dartdocInfo,
2525
CompilationUnit unit,
2626
int offset, {
2727
this.documentationPreference = DocumentationPreference.full,
28-
}) : _node = NodeLocator(offset).searchWithin(unit);
28+
}) : _documentationComputer = DartDocumentationComputer(dartdocInfo),
29+
_node = NodeLocator(offset).searchWithin(unit);
2930

3031
/// The [ArgumentList] node located by [compute].
3132
ArgumentList get argumentList => _argumentList;
@@ -75,8 +76,7 @@ class DartUnitSignatureComputer {
7576

7677
_argumentList = argumentList;
7778
var convertedParameters = parameters.map((p) => _convertParam(p)).toList();
78-
var dartdoc = DartUnitHoverComputer.computePreferredDocumentation(
79-
_dartdocInfo,
79+
var dartdoc = _documentationComputer.computePreferred(
8080
element,
8181
documentationPreference,
8282
);

pkg/analysis_server/lib/src/computer/computer_type_arguments_signature.dart

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp;
6-
import 'package:analysis_server/src/computer/computer_hover.dart';
6+
import 'package:analysis_server/src/computer/computer_documentation.dart';
77
import 'package:analysis_server/src/lsp/dartdoc.dart';
88
import 'package:analysis_server/src/lsp/mapping.dart';
99
import 'package:analyzer/dart/ast/ast.dart';
@@ -16,19 +16,20 @@ import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
1616
/// the [TypeArgumentList] surrounding the specified offset of a Dart
1717
/// [CompilationUnit].
1818
class DartTypeArgumentsSignatureComputer {
19-
final DartdocDirectiveInfo _dartdocInfo;
2019
final AstNode? _node;
2120
final Set<lsp.MarkupKind>? preferredFormats;
2221
late TypeArgumentList _argumentList;
2322
final DocumentationPreference documentationPreference;
23+
final DartDocumentationComputer _documentationComputer;
2424

2525
DartTypeArgumentsSignatureComputer(
26-
this._dartdocInfo,
26+
DartdocDirectiveInfo dartdocInfo,
2727
CompilationUnit unit,
2828
int offset,
2929
this.preferredFormats, {
3030
this.documentationPreference = DocumentationPreference.full,
31-
}) : _node = NodeLocator(offset).searchWithin(unit);
31+
}) : _documentationComputer = DartDocumentationComputer(dartdocInfo),
32+
_node = NodeLocator(offset).searchWithin(unit);
3233

3334
/// The [TypeArgumentList] node located by [compute].
3435
TypeArgumentList get argumentList => _argumentList;
@@ -56,8 +57,8 @@ class DartTypeArgumentsSignatureComputer {
5657
_argumentList = argumentList;
5758

5859
var label = element.getDisplayString();
59-
var documentation = DartUnitHoverComputer.computePreferredDocumentation(
60-
_dartdocInfo, element, documentationPreference);
60+
var documentation = _documentationComputer.computePreferred(
61+
element, documentationPreference);
6162

6263
return _toSignatureHelp(
6364
label,

pkg/analysis_server/lib/src/lsp/client_configuration.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analysis_server/src/computer/computer_hover.dart';
5+
import 'package:analysis_server/src/computer/computer_documentation.dart';
66
import 'package:collection/collection.dart';
77
import 'package:path/path.dart' as path;
88

pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import 'dart:math' as math;
66

77
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
8-
import 'package:analysis_server/src/computer/computer_hover.dart';
8+
import 'package:analysis_server/src/computer/computer_documentation.dart';
99
import 'package:analysis_server/src/lsp/client_capabilities.dart';
1010
import 'package:analysis_server/src/lsp/constants.dart';
1111
import 'package:analysis_server/src/lsp/error_or.dart';

pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Element;
6-
import 'package:analysis_server/src/computer/computer_hover.dart';
6+
import 'package:analysis_server/src/computer/computer_documentation.dart';
77
import 'package:analysis_server/src/lsp/client_capabilities.dart';
88
import 'package:analysis_server/src/lsp/constants.dart';
99
import 'package:analysis_server/src/lsp/error_or.dart';
@@ -129,9 +129,8 @@ class CompletionResolveHandler
129129
if (element != null) {
130130
var formats = clientCapabilities.completionDocumentationFormats;
131131
var dartDocInfo = server.getDartdocDirectiveInfoForSession(session);
132-
var dartDoc = DartUnitHoverComputer.computePreferredDocumentation(
133-
dartDocInfo,
134-
element,
132+
var dartDocComputer = DartDocumentationComputer(dartDocInfo);
133+
var dartDoc = dartDocComputer.computePreferred(element,
135134
server.lspClientConfiguration.global.preferredDocumentation);
136135
// `dartDoc` can be both null or empty.
137136
documentation = dartDoc != null && dartDoc.isNotEmpty

pkg/analysis_server/lib/src/lsp/mapping.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp;
66
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
77
import 'package:analysis_server/src/analysis_server.dart';
88
import 'package:analysis_server/src/collections.dart';
9-
import 'package:analysis_server/src/computer/computer_hover.dart';
9+
import 'package:analysis_server/src/computer/computer_documentation.dart';
1010
import 'package:analysis_server/src/lsp/client_capabilities.dart';
1111
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
1212
import 'package:analysis_server/src/lsp/constants.dart';

0 commit comments

Comments
 (0)