Skip to content

Commit 2d1ae23

Browse files
Merge pull request #94 from Workiva/populate_diagnostics
FEA-2796: Occurrence Diagnostics
2 parents 60b508d + 873ee46 commit 2d1ae23

File tree

4 files changed

+74
-9
lines changed

4 files changed

+74
-9
lines changed

lib/src/indexer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Future<Index> indexPackage(
8585
relativePath,
8686
dirPath,
8787
resUnit.lineInfo,
88+
resUnit.errors,
8889
packageConfig,
8990
pubspec,
9091
);

lib/src/metadata.dart

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
1+
import 'package:analyzer/dart/ast/ast.dart';
12
import 'package:analyzer/dart/element/element.dart';
3+
import 'package:analyzer/diagnostic/diagnostic.dart';
4+
import 'package:analyzer/error/error.dart';
5+
import 'package:scip_dart/src/gen/scip.pb.dart' as proto;
6+
7+
/// The collection of AnalysisHint codes that should be considered "Unused".
8+
/// Annoyingly dart does not export their AnalysisHint, if this ever changes
9+
/// these should directly reference the instances within:
10+
/// https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/lib/src/error/codes.g.dart
11+
const _unusedHintCodes = {
12+
'UNUSED_CATCH_CLAUSE',
13+
'UNUSED_CATCH_STACK',
14+
'UNUSED_ELEMENT',
15+
'UNUSED_ELEMENT_PARAMETER',
16+
'UNUSED_FIELD',
17+
'UNUSED_IMPORT',
18+
'UNUSED_LABEL',
19+
'UNUSED_RESULT',
20+
'UNUSED_SHOWN_NAME',
21+
};
222

323
/// Refers to any additional metadata attached to a `SymbolInformation`
424
/// struct on the protobuf spec.
@@ -8,14 +28,20 @@ import 'package:analyzer/dart/element/element.dart';
828
class SymbolMetadata {
929
List<String> documentation;
1030

11-
SymbolMetadata({required this.documentation});
31+
List<proto.Diagnostic>? diagnostics;
32+
33+
SymbolMetadata({required this.documentation, this.diagnostics});
1234
}
1335

1436
/// Returns a [SymbolMetadata] object for a provided [Element] type.
1537
///
1638
/// This information is used to embellish `SymbolInformation` struct's
1739
/// within the protobuf schema for scip
18-
SymbolMetadata getSymbolMetadata(Element element) {
40+
SymbolMetadata getSymbolMetadata(
41+
Element element,
42+
AstNode node,
43+
List<AnalysisError> analysisErrors,
44+
) {
1945
final displayString = element.getDisplayString(
2046
withNullability: false,
2147
multiline: true,
@@ -26,10 +52,37 @@ SymbolMetadata getSymbolMetadata(Element element) {
2652
'',
2753
);
2854

55+
final diagnostics = analysisErrors
56+
.where((error) => error.offset == node.offset)
57+
.map((error) => proto.Diagnostic(
58+
code: error.errorCode.name,
59+
message: error.message,
60+
severity: error.severity.toProto(),
61+
tags: [
62+
if (element.hasDeprecated) proto.DiagnosticTag.Deprecated,
63+
if (_unusedHintCodes.contains(error.errorCode.uniqueName))
64+
proto.DiagnosticTag.Unnecessary,
65+
]))
66+
.toList();
67+
2968
return SymbolMetadata(
3069
documentation: [
3170
'```dart\n$displayString\n```',
3271
if (docComment != null) docComment
3372
],
73+
diagnostics: diagnostics.isNotEmpty ? diagnostics : null,
3474
);
3575
}
76+
77+
extension _SeverityConverter on Severity {
78+
proto.Severity toProto() {
79+
switch (this) {
80+
case Severity.error:
81+
return proto.Severity.Error;
82+
case Severity.warning:
83+
return proto.Severity.Warning;
84+
case Severity.info:
85+
return proto.Severity.Information;
86+
}
87+
}
88+
}

lib/src/scip_visitor.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:analyzer/dart/ast/ast.dart';
22
import 'package:analyzer/dart/ast/visitor.dart';
33
import 'package:analyzer/dart/element/element.dart';
4+
import 'package:analyzer/error/error.dart';
45
import 'package:analyzer/source/line_info.dart';
56
import 'package:package_config/package_config.dart';
67
import 'package:pubspec_parse/pubspec_parse.dart';
@@ -17,6 +18,7 @@ class ScipVisitor extends GeneralizingAstVisitor {
1718
final String _relativePath;
1819
final String _projectRoot;
1920
final LineInfo _lineInfo;
21+
final List<AnalysisError> _analysisErrors;
2022

2123
final SymbolGenerator _symbolGenerator;
2224

@@ -27,6 +29,7 @@ class ScipVisitor extends GeneralizingAstVisitor {
2729
this._relativePath,
2830
this._projectRoot,
2931
this._lineInfo,
32+
this._analysisErrors,
3033
PackageConfig packageConfig,
3134
Pubspec pubspec,
3235
) : _symbolGenerator = SymbolGenerator(
@@ -71,6 +74,7 @@ class ScipVisitor extends GeneralizingAstVisitor {
7174

7275
_registerAsDefinition(
7376
element,
77+
node,
7478
relationships: relationships,
7579
);
7680
}
@@ -91,12 +95,13 @@ class ScipVisitor extends GeneralizingAstVisitor {
9195
final fieldElement = (element as FieldFormalParameterElement).field;
9296
_registerAsReference(
9397
fieldElement!,
98+
node,
9499
offset: node.thisKeyword.offset,
95100
length: node.thisKeyword.length,
96101
);
97102
}
98103

99-
_registerAsDefinition(element);
104+
_registerAsDefinition(element, node);
100105
}
101106

102107
void _visitSimpleIdentifier(SimpleIdentifier node) {
@@ -135,10 +140,11 @@ class ScipVisitor extends GeneralizingAstVisitor {
135140
if (element == null || element.source == null) return;
136141

137142
if (node.inDeclarationContext()) {
138-
_registerAsDefinition(element);
143+
_registerAsDefinition(element, node);
139144
} else {
140145
_registerAsReference(
141146
element,
147+
node,
142148
offset: node.offset,
143149
length: node.name.length,
144150
);
@@ -153,22 +159,25 @@ class ScipVisitor extends GeneralizingAstVisitor {
153159
/// If [element] exists outside of the projects source, it will be added to the
154160
/// [globalExternalSymbols].
155161
void _registerAsReference(
156-
Element element, {
162+
Element element,
163+
AstNode node, {
157164
required int offset,
158165
required int length,
159166
}) {
160167
final symbol = _symbolGenerator.symbolFor(element);
161168
if (symbol != null) {
169+
final meta = getSymbolMetadata(element, node, _analysisErrors);
162170
occurrences.add(Occurrence(
163171
range: _lineInfo.getRange(offset, length),
164172
symbol: symbol,
173+
diagnostics: meta.diagnostics,
165174
));
166175

167176
if (!element.source!.fullName.startsWith(_projectRoot)) {
168177
if (!globalExternalSymbols.any(
169178
(symbolInfo) => symbolInfo.symbol == symbol,
170179
)) {
171-
final meta = getSymbolMetadata(element);
180+
final meta = getSymbolMetadata(element, node, _analysisErrors);
172181
globalExternalSymbols.add(SymbolInformation(
173182
symbol: symbol,
174183
documentation: meta.documentation,
@@ -183,12 +192,13 @@ class ScipVisitor extends GeneralizingAstVisitor {
183192
/// This adds both a symbol, and an occurrence for the element and it's
184193
/// name
185194
void _registerAsDefinition(
186-
Element element, {
195+
Element element,
196+
AstNode node, {
187197
List<Relationship>? relationships,
188198
}) {
189199
final symbol = _symbolGenerator.symbolFor(element);
190200
if (symbol != null) {
191-
final meta = getSymbolMetadata(element);
201+
final meta = getSymbolMetadata(element, node, _analysisErrors);
192202
symbols.add(SymbolInformation(
193203
symbol: symbol,
194204
documentation: meta.documentation,
@@ -199,6 +209,7 @@ class ScipVisitor extends GeneralizingAstVisitor {
199209
range: _lineInfo.getRange(element.nameOffset, element.nameLength),
200210
symbol: symbol,
201211
symbolRoles: SymbolRole.Definition.value,
212+
diagnostics: meta.diagnostics,
202213
));
203214
}
204215
}

pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ packages:
112112
name: collection
113113
url: "https://pub.dartlang.org"
114114
source: hosted
115-
version: "1.17.2"
115+
version: "1.18.0"
116116
convert:
117117
dependency: transitive
118118
description:

0 commit comments

Comments
 (0)