mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 16:13:19 +00:00
[linter] Publish new linter diagnostic messages
This CL doesn't set up the analyzer to surface links to these destinations, just includes the new format in the diagnostic messages file. Change-Id: I6c227448b42a5abac53d5c6a863e599c7e8809da Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368081 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com> Commit-Queue: Marya Belanger <mbelanger@google.com>
This commit is contained in:
parent
d9ff61bd87
commit
83135245b2
File diff suppressed because it is too large
Load diff
|
@ -36,7 +36,7 @@ class DiagnosticInformation {
|
|||
final String name;
|
||||
|
||||
/// The messages associated with the diagnostic.
|
||||
List<String> messages;
|
||||
final List<String> messages;
|
||||
|
||||
/// The previous names by which this diagnostic has been known.
|
||||
List<String> previousNames = [];
|
||||
|
@ -46,7 +46,7 @@ class DiagnosticInformation {
|
|||
|
||||
/// Initialize a newly created information holder with the given [name] and
|
||||
/// [message].
|
||||
DiagnosticInformation(this.name, String message) : messages = [message];
|
||||
DiagnosticInformation(this.name, this.messages);
|
||||
|
||||
/// Return `true` if this diagnostic has documentation.
|
||||
bool get hasDocumentation => documentation != null;
|
||||
|
@ -58,6 +58,12 @@ class DiagnosticInformation {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add the list of [messages] to the list of messages
|
||||
/// associated with the diagnostic.
|
||||
void addMessages(List<String> messages) {
|
||||
messages.forEach(addMessage);
|
||||
}
|
||||
|
||||
void addPreviousName(String previousName) {
|
||||
if (!previousNames.contains(previousName)) {
|
||||
previousNames.add(previousName);
|
||||
|
@ -118,6 +124,9 @@ class DocumentationGenerator {
|
|||
for (var classEntry in analyzerMessages.entries) {
|
||||
_extractAllDocs(classEntry.key, classEntry.value);
|
||||
}
|
||||
for (var classEntry in lintMessages.entries) {
|
||||
_extractAllDocs(classEntry.key, classEntry.value);
|
||||
}
|
||||
for (var errorClass in errorClasses) {
|
||||
if (errorClass.includeCfeMessages) {
|
||||
_extractAllDocs(
|
||||
|
@ -147,14 +156,12 @@ class DocumentationGenerator {
|
|||
}
|
||||
var name = errorCodeInfo.sharedName ?? errorName;
|
||||
var info = infoByName[name];
|
||||
var message = convertTemplate(
|
||||
errorCodeInfo.computePlaceholderToIndexMap(),
|
||||
errorCodeInfo.problemMessage);
|
||||
var messages = errorCodeInfo.formattedProblemMessages;
|
||||
if (info == null) {
|
||||
info = DiagnosticInformation(name, message);
|
||||
info = DiagnosticInformation(name, messages);
|
||||
infoByName[name] = info;
|
||||
} else {
|
||||
info.addMessage(message);
|
||||
info.addMessages(messages);
|
||||
}
|
||||
var previousName = errorCodeInfo.previousName;
|
||||
if (previousName != null) {
|
||||
|
@ -196,7 +203,7 @@ that might work in unexpected ways.
|
|||
|
||||
[bottom type]: https://dart.dev/null-safety/understanding-null-safety#top-and-bottom
|
||||
[debugPrint]: https://api.flutter.dev/flutter/foundation/debugPrint.html
|
||||
[ffi]: https://dart.dev/guides/libraries/c-interop
|
||||
[ffi]: https://dart.dev/interop/c-interop
|
||||
[IEEE 754]: https://en.wikipedia.org/wiki/IEEE_754
|
||||
[irrefutable pattern]: https://dart.dev/resources/glossary#irrefutable-pattern
|
||||
[kDebugMode]: https://api.flutter.dev/flutter/foundation/kDebugMode-constant.html
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:analyzer/src/lint/registry.dart' as linter;
|
||||
import 'package:analyzer_utilities/package_root.dart' as pkg_root;
|
||||
import 'package:linter/src/rules.dart' as linter;
|
||||
import 'package:path/path.dart';
|
||||
import 'package:yaml/yaml.dart' show loadYaml;
|
||||
|
||||
|
@ -214,6 +216,7 @@ Map<String, FrontEndErrorCodeInfo> decodeCfeMessagesYaml(Object? yaml) {
|
|||
/// error name.
|
||||
Map<String, Map<String, AnalyzerErrorCodeInfo>> decodeLinterMessagesYaml(
|
||||
Object? yaml) {
|
||||
linter.registerLintRules();
|
||||
Never problem(String message) {
|
||||
throw 'Problem in pkg/linter/messages.yaml: $message';
|
||||
}
|
||||
|
@ -264,7 +267,7 @@ Map<String, Map<String, AnalyzerErrorCodeInfo>> decodeLinterMessagesYaml(
|
|||
aliasFor: aliasFor, comment: errorValue['comment'] as String?);
|
||||
} else {
|
||||
(result[className] ??= {})[errorName] =
|
||||
AnalyzerErrorCodeInfo.fromLinterYaml(errorValue);
|
||||
LinterRuleInfo.fromYaml(errorName, errorValue);
|
||||
}
|
||||
} catch (e) {
|
||||
problem('while processing $className.$errorName, $e');
|
||||
|
@ -288,7 +291,7 @@ Map<String, FrontEndErrorCodeInfo> _loadFrontEndMessages() {
|
|||
return decodeCfeMessagesYaml(messagesYaml);
|
||||
}
|
||||
|
||||
/// Loads linter messages from the linters's `messages.yaml` file.
|
||||
/// Loads linter messages from the linter's `messages.yaml` file.
|
||||
Map<String, Map<String, AnalyzerErrorCodeInfo>> _loadLintMessages() {
|
||||
Object? messagesYaml =
|
||||
loadYaml(File(join(linterPkgPath, 'messages.yaml')).readAsStringSync());
|
||||
|
@ -354,6 +357,10 @@ class AliasErrorCodeInfo extends AnalyzerErrorCodeInfo {
|
|||
String get aliasForFilePath => errorClasses
|
||||
.firstWhere((element) => element.name == aliasForClass)
|
||||
.filePath;
|
||||
|
||||
@override
|
||||
List<String> get formattedProblemMessages => throw StateError(
|
||||
'The problem message of an error code should not be used.');
|
||||
}
|
||||
|
||||
/// In-memory representation of error code information obtained from the
|
||||
|
@ -371,9 +378,10 @@ class AnalyzerErrorCodeInfo extends ErrorCodeInfo {
|
|||
super.sharedName,
|
||||
});
|
||||
|
||||
AnalyzerErrorCodeInfo.fromLinterYaml(super.yaml) : super.fromLinterYaml();
|
||||
|
||||
AnalyzerErrorCodeInfo.fromYaml(super.yaml) : super.fromYaml();
|
||||
|
||||
@override
|
||||
List<String> get formattedProblemMessages => [problemMessage];
|
||||
}
|
||||
|
||||
/// Data tables mapping between CFE errors and their corresponding automatically
|
||||
|
@ -561,13 +569,6 @@ abstract class ErrorCodeInfo {
|
|||
this.removedIn,
|
||||
});
|
||||
|
||||
/// Decodes an [ErrorCodeInfo] object from its YAML representation.
|
||||
ErrorCodeInfo.fromLinterYaml(Map<Object?, Object?> yaml)
|
||||
: this(
|
||||
documentation: yaml['documentation'] as String?,
|
||||
hasPublishedDocs: yaml['hasPublishedDocs'] as bool? ?? false,
|
||||
problemMessage: '');
|
||||
|
||||
/// Decodes an [ErrorCodeInfo] object from its YAML representation.
|
||||
ErrorCodeInfo.fromYaml(Map<Object?, Object?> yaml)
|
||||
: this(
|
||||
|
@ -583,6 +584,8 @@ abstract class ErrorCodeInfo {
|
|||
removedIn: yaml['removedIn'] as String?,
|
||||
previousName: yaml['previousName'] as String?);
|
||||
|
||||
List<String> get formattedProblemMessages;
|
||||
|
||||
/// If this error is no longer reported and
|
||||
/// its error codes should no longer be generated.
|
||||
bool get isRemoved => removedIn != null;
|
||||
|
@ -680,6 +683,10 @@ class FrontEndErrorCodeInfo extends ErrorCodeInfo {
|
|||
index = yaml['index'] as int?,
|
||||
super.fromYaml();
|
||||
|
||||
@override
|
||||
List<String> get formattedProblemMessages =>
|
||||
[convertTemplate(computePlaceholderToIndexMap(), problemMessage)];
|
||||
|
||||
@override
|
||||
Map<Object?, Object?> toYaml() => {
|
||||
if (analyzerCode.isNotEmpty)
|
||||
|
@ -708,3 +715,33 @@ class FrontEndErrorCodeInfo extends ErrorCodeInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory representation of error code information obtained from the
|
||||
/// linter's `messages.yaml` file.
|
||||
class LinterRuleInfo extends AnalyzerErrorCodeInfo {
|
||||
final List<String> problemMessages;
|
||||
|
||||
/// Decodes an [LinterRuleInfo] object from its [ruleName] and
|
||||
/// its [yaml] representation.
|
||||
factory LinterRuleInfo.fromYaml(String ruleName, Map<Object?, Object?> yaml) {
|
||||
var lint = linter.Registry.ruleRegistry[ruleName]!;
|
||||
var problemMessages = lint.lintCodes
|
||||
.map((code) => code.problemMessage)
|
||||
.toList(growable: false);
|
||||
|
||||
return LinterRuleInfo._(
|
||||
documentation: yaml['documentation'] as String?,
|
||||
hasPublishedDocs: yaml['hasPublishedDocs'] as bool? ?? false,
|
||||
problemMessages: problemMessages,
|
||||
);
|
||||
}
|
||||
|
||||
LinterRuleInfo._({
|
||||
required this.problemMessages,
|
||||
required super.documentation,
|
||||
required super.hasPublishedDocs,
|
||||
}) : super(problemMessage: problemMessages.firstOrNull ?? '');
|
||||
|
||||
@override
|
||||
List<String> get formattedProblemMessages => problemMessages;
|
||||
}
|
||||
|
|
|
@ -159,7 +159,8 @@ LintCode:
|
|||
The analyzer produces this diagnostic when the statement after an `else`
|
||||
is an empty statement (a semicolon).
|
||||
|
||||
For more information, see the documentation for [avoid_empty_else][].
|
||||
For more information, see the documentation for
|
||||
[`avoid_empty_else`](https://dart.dev/diagnostics/avoid_empty_else).
|
||||
|
||||
#### Example
|
||||
|
||||
|
@ -302,7 +303,8 @@ LintCode:
|
|||
#### Common fixes
|
||||
|
||||
If you're writing code that uses Flutter, then use the function
|
||||
`[debugPrint][]`, guarded by a test using `[kDebugMode][]`:
|
||||
[`debugPrint`][debugPrint], guarded by a test
|
||||
using [`kDebugMode`][kDebugMode]:
|
||||
|
||||
```dart
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -315,7 +317,7 @@ LintCode:
|
|||
```
|
||||
|
||||
If you're writing code that doesn't use Flutter, then use a logging
|
||||
service, such as `[package:logging][package-logging]`, to write the
|
||||
service, such as [`package:logging`][package-logging], to write the
|
||||
information.
|
||||
avoid_relative_lib_imports:
|
||||
documentation: |-
|
||||
|
@ -1042,7 +1044,7 @@ LintCode:
|
|||
|
||||
The analyzer produces this diagnostic when a documentation comment that
|
||||
appears to be library documentation isn't followed by a `library`
|
||||
directive. More specificially, it is produced when a documentation comment
|
||||
directive. More specifically, it is produced when a documentation comment
|
||||
appears before the first directive in the library, assuming that it isn't
|
||||
a `library` directive, or before the first top-level declaration and is
|
||||
separated from the declaration by one or more blank lines.
|
||||
|
@ -1989,7 +1991,7 @@ LintCode:
|
|||
For example, given a package named `my_package`, here are the library
|
||||
names for various files in the package:
|
||||
|
||||
```
|
||||
```dart
|
||||
// In lib/my_package.dart
|
||||
library my_package;
|
||||
|
||||
|
|
Loading…
Reference in a new issue