[analyzer] Stop generating the diagnostics.md file
dart.dev now consumes the source YAML files, so generating the Markdown file is no longer necessary. The contents of the YAML files are still verified as before. Resolves https://github.com/dart-lang/site-www/issues/6387 Change-Id: I8b989b598ec3c7abef66242dceb9d5a481f43e39 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/407640 Reviewed-by: Phil Quitslund <pquitslund@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Auto-Submit: Parker Lougheed <parlough@gmail.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
Commit Queue
parent
7bb0c4cdf4
commit
d678a7e191
@@ -3,11 +3,9 @@
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../tool/diagnostics/generate.dart';
|
||||
import '../tool/messages/error_code_documentation_info.dart';
|
||||
import '../tool/messages/error_code_info.dart';
|
||||
import 'src/dart/resolution/context_collection_resolution.dart';
|
||||
@@ -421,25 +419,6 @@ class VerifyDiagnosticsTest {
|
||||
//
|
||||
DocumentationValidator validator = DocumentationValidator();
|
||||
await validator.validate();
|
||||
//
|
||||
// Validate that the generator has been run.
|
||||
//
|
||||
String actualContent = PhysicalResourceProvider.INSTANCE
|
||||
.getFile(computeOutputPath())
|
||||
.readAsStringSync();
|
||||
// Normalize Windows line endings to Unix line endings so that the
|
||||
// comparison doesn't fail on Windows.
|
||||
actualContent = actualContent.replaceAll('\r\n', '\n');
|
||||
|
||||
StringBuffer sink = StringBuffer();
|
||||
DocumentationGenerator generator = DocumentationGenerator();
|
||||
generator.writeDocumentation(sink);
|
||||
String expectedContent = sink.toString();
|
||||
|
||||
if (actualContent != expectedContent) {
|
||||
fail('The diagnostic documentation needs to be regenerated.\n'
|
||||
'Please run tool/diagnostics/generate.dart.');
|
||||
}
|
||||
}
|
||||
|
||||
test_published() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,268 +0,0 @@
|
||||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// 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 'dart:io';
|
||||
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer_utilities/package_root.dart' as package_root;
|
||||
|
||||
import '../messages/error_code_documentation_info.dart';
|
||||
import '../messages/error_code_info.dart';
|
||||
|
||||
/// Generate the file `diagnostics.md` based on the documentation associated
|
||||
/// with the declarations of the error codes.
|
||||
Future<void> main() async {
|
||||
var sink = File(computeOutputPath()).openWrite();
|
||||
var generator = DocumentationGenerator();
|
||||
generator.writeDocumentation(sink);
|
||||
await sink.flush();
|
||||
await sink.close();
|
||||
}
|
||||
|
||||
/// Compute the path to the file into which documentation is being generated.
|
||||
String computeOutputPath() {
|
||||
var pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
|
||||
var packageRoot = pathContext.normalize(package_root.packageRoot);
|
||||
var analyzerPath = pathContext.join(packageRoot, 'analyzer');
|
||||
return pathContext.join(
|
||||
analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');
|
||||
}
|
||||
|
||||
/// An information holder containing information about a diagnostic that was
|
||||
/// extracted from the instance creation expression.
|
||||
class DiagnosticInformation {
|
||||
/// The name of the diagnostic.
|
||||
final String name;
|
||||
|
||||
/// The messages associated with the diagnostic.
|
||||
final List<String> messages;
|
||||
|
||||
/// The previous names by which this diagnostic has been known.
|
||||
List<String> previousNames = [];
|
||||
|
||||
/// The documentation text associated with the diagnostic.
|
||||
String? documentation;
|
||||
|
||||
/// Initialize a newly created information holder with the given [name] and
|
||||
/// [message].
|
||||
DiagnosticInformation(this.name, String message) : messages = [message];
|
||||
|
||||
/// Return `true` if this diagnostic has documentation.
|
||||
bool get hasDocumentation => documentation != null;
|
||||
|
||||
/// Add the [message] to the list of messages associated with the diagnostic.
|
||||
void addMessage(String message) {
|
||||
if (!messages.contains(message)) {
|
||||
messages.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
void addPreviousName(String previousName) {
|
||||
if (!previousNames.contains(previousName)) {
|
||||
previousNames.add(previousName);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the full documentation for this diagnostic.
|
||||
void writeOn(StringSink sink) {
|
||||
messages.sort();
|
||||
sink.writeln('### ${name.toLowerCase()}');
|
||||
for (var previousName in previousNames) {
|
||||
sink.writeln();
|
||||
var previousInLowerCase = previousName.toLowerCase();
|
||||
sink.writeln('<a id="$previousInLowerCase" aria-hidden="true"></a>'
|
||||
'_(Previously known as `$previousInLowerCase`)_');
|
||||
}
|
||||
for (String message in messages) {
|
||||
sink.writeln();
|
||||
for (String line in _split('_${_escape(message)}_')) {
|
||||
sink.writeln(line);
|
||||
}
|
||||
}
|
||||
sink.writeln();
|
||||
sink.writeln(documentation!);
|
||||
}
|
||||
|
||||
/// Return a version of the [text] in which characters that have special
|
||||
/// meaning in markdown have been escaped.
|
||||
String _escape(String text) {
|
||||
return text.replaceAll('_', '\\_');
|
||||
}
|
||||
|
||||
/// Split the [message] into multiple lines, each of which is less than 80
|
||||
/// characters long.
|
||||
List<String> _split(String message) {
|
||||
// This uses a brute force approach because we don't expect to have messages
|
||||
// that need to be split more than once.
|
||||
int length = message.length;
|
||||
if (length <= 80) {
|
||||
return [message];
|
||||
}
|
||||
int endIndex = message.lastIndexOf(' ', 80);
|
||||
if (endIndex < 0) {
|
||||
return [message];
|
||||
}
|
||||
return [message.substring(0, endIndex), message.substring(endIndex + 1)];
|
||||
}
|
||||
}
|
||||
|
||||
/// A class used to generate diagnostic documentation.
|
||||
class DocumentationGenerator {
|
||||
/// A map from the name of a diagnostic to the information about that
|
||||
/// diagnostic.
|
||||
Map<String, DiagnosticInformation> infoByName = {};
|
||||
|
||||
/// Initialize a newly created documentation generator.
|
||||
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(
|
||||
errorClass.name, cfeToAnalyzerErrorCodeTables.analyzerCodeToInfo);
|
||||
// Note: only one error class has the `includeCfeMessages` flag set;
|
||||
// verify_diagnostics_test.dart verifies this. So we can safely break.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the documentation to [sink].
|
||||
void writeDocumentation(StringSink sink) {
|
||||
_writeHeader(sink);
|
||||
_writeGlossary(sink);
|
||||
_writeDiagnostics(sink);
|
||||
}
|
||||
|
||||
/// Extract documentation from all of the files containing the definitions of
|
||||
/// diagnostics.
|
||||
void _extractAllDocs(String className, Map<String, ErrorCodeInfo> messages) {
|
||||
for (var errorEntry in messages.entries) {
|
||||
var errorName = errorEntry.key;
|
||||
var errorCodeInfo = errorEntry.value;
|
||||
if (errorCodeInfo is AliasErrorCodeInfo) {
|
||||
continue;
|
||||
}
|
||||
var name = errorCodeInfo.sharedName ?? errorName;
|
||||
var info = infoByName[name];
|
||||
var message = convertTemplate(
|
||||
errorCodeInfo.computePlaceholderToIndexMap(),
|
||||
errorCodeInfo.problemMessage);
|
||||
if (info == null) {
|
||||
info = DiagnosticInformation(name, message);
|
||||
infoByName[name] = info;
|
||||
} else {
|
||||
info.addMessage(message);
|
||||
}
|
||||
var previousName = errorCodeInfo.previousName;
|
||||
if (previousName != null) {
|
||||
info.addPreviousName(previousName);
|
||||
}
|
||||
var docs = _extractDoc('$className.$errorName', errorCodeInfo);
|
||||
if (docs.isNotEmpty) {
|
||||
if (info.documentation != null) {
|
||||
throw StateError(
|
||||
'Documentation defined multiple times for ${info.name}');
|
||||
}
|
||||
info.documentation = docs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract documentation from the given [errorCodeInfo].
|
||||
String _extractDoc(String errorCode, ErrorCodeInfo errorCodeInfo) {
|
||||
var parsedComment =
|
||||
parseErrorCodeDocumentation(errorCode, errorCodeInfo.documentation);
|
||||
if (parsedComment == null) {
|
||||
return '';
|
||||
}
|
||||
return [
|
||||
for (var documentationPart in parsedComment)
|
||||
documentationPart.formatForDocumentation()
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
/// Write the documentation for all of the diagnostics.
|
||||
void _writeDiagnostics(StringSink sink) {
|
||||
sink.write('''
|
||||
|
||||
## Diagnostics
|
||||
|
||||
The analyzer produces the following diagnostics for code that
|
||||
doesn't conform to the language specification or
|
||||
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/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
|
||||
[meta-doNotStore]: https://pub.dev/documentation/meta/latest/meta/doNotStore-constant.html
|
||||
[meta-doNotSubmit]: https://pub.dev/documentation/meta/latest/meta/doNotSubmit-constant.html
|
||||
[meta-factory]: https://pub.dev/documentation/meta/latest/meta/factory-constant.html
|
||||
[meta-immutable]: https://pub.dev/documentation/meta/latest/meta/immutable-constant.html
|
||||
[meta-internal]: https://pub.dev/documentation/meta/latest/meta/internal-constant.html
|
||||
[meta-literal]: https://pub.dev/documentation/meta/latest/meta/literal-constant.html
|
||||
[meta-mustBeConst]: https://pub.dev/documentation/meta/latest/meta/mustBeConst-constant.html
|
||||
[meta-mustCallSuper]: https://pub.dev/documentation/meta/latest/meta/mustCallSuper-constant.html
|
||||
[meta-optionalTypeArgs]: https://pub.dev/documentation/meta/latest/meta/optionalTypeArgs-constant.html
|
||||
[meta-sealed]: https://pub.dev/documentation/meta/latest/meta/sealed-constant.html
|
||||
[meta-useResult]: https://pub.dev/documentation/meta/latest/meta/useResult-constant.html
|
||||
[meta-UseResult]: https://pub.dev/documentation/meta/latest/meta/UseResult-class.html
|
||||
[meta-visibleForOverriding]: https://pub.dev/documentation/meta/latest/meta/visibleForOverriding-constant.html
|
||||
[meta-visibleForTesting]: https://pub.dev/documentation/meta/latest/meta/visibleForTesting-constant.html
|
||||
[package-logging]: https://pub.dev/packages/logging
|
||||
[refutable pattern]: https://dart.dev/resources/glossary#refutable-pattern
|
||||
''');
|
||||
var errorCodes = infoByName.keys.toList();
|
||||
errorCodes.sort();
|
||||
for (String errorCode in errorCodes) {
|
||||
var info = infoByName[errorCode]!;
|
||||
if (info.hasDocumentation) {
|
||||
sink.writeln();
|
||||
info.writeOn(sink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Link to the glossary.
|
||||
void _writeGlossary(StringSink sink) {
|
||||
sink.write(r'''
|
||||
|
||||
[constant context]: /resources/glossary#constant-context
|
||||
[definite assignment]: /resources/glossary#definite-assignment
|
||||
[mixin application]: /resources/glossary#mixin-application
|
||||
[override inference]: /resources/glossary#override-inference
|
||||
[part file]: /resources/glossary#part-file
|
||||
[potentially non-nullable]: /resources/glossary#potentially-non-nullable
|
||||
[public library]: /resources/glossary#public-library
|
||||
''');
|
||||
}
|
||||
|
||||
/// Write the header of the file.
|
||||
void _writeHeader(StringSink sink) {
|
||||
sink.write('''
|
||||
---
|
||||
title: Diagnostic messages
|
||||
description: Details for diagnostics produced by the Dart analyzer.
|
||||
body_class: highlight-diagnostics
|
||||
---
|
||||
{%- comment %}
|
||||
WARNING: Do NOT EDIT this file directly. It is autogenerated by the script in
|
||||
`pkg/analyzer/tool/diagnostics/generate.dart` in the sdk repository.
|
||||
Update instructions: https://github.com/dart-lang/site-www/issues/1949
|
||||
{% endcomment -%}
|
||||
|
||||
This page lists diagnostic messages produced by the Dart analyzer,
|
||||
with details about what those messages mean and how you can fix your code.
|
||||
For more information about the analyzer, see
|
||||
[Customizing static analysis](/tools/analysis).
|
||||
''');
|
||||
}
|
||||
}
|
||||
@@ -63,19 +63,12 @@ class ErrorCodeDocumentationBlock extends ErrorCodeDocumentationPart {
|
||||
required this.fileType,
|
||||
this.languageVersion,
|
||||
this.uri});
|
||||
|
||||
@override
|
||||
String formatForDocumentation() => ['```$fileType', text, '```'].join('\n');
|
||||
}
|
||||
|
||||
/// A portion of an error code's documentation. This could be free form
|
||||
/// markdown text ([ErrorCodeDocumentationText]) or a code block
|
||||
/// ([ErrorCodeDocumentationBlock]).
|
||||
abstract class ErrorCodeDocumentationPart {
|
||||
/// Formats this documentation part as text suitable for inclusion in the
|
||||
/// analyzer's `diagnostics.md` file.
|
||||
String formatForDocumentation();
|
||||
}
|
||||
abstract class ErrorCodeDocumentationPart {}
|
||||
|
||||
/// An [ErrorCodeDocumentationPart] containing free form markdown text.
|
||||
class ErrorCodeDocumentationText extends ErrorCodeDocumentationPart {
|
||||
@@ -83,9 +76,6 @@ class ErrorCodeDocumentationText extends ErrorCodeDocumentationPart {
|
||||
final String text;
|
||||
|
||||
ErrorCodeDocumentationText(this.text);
|
||||
|
||||
@override
|
||||
String formatForDocumentation() => text;
|
||||
}
|
||||
|
||||
class _ErrorCodeDocumentationParser {
|
||||
|
||||
@@ -67,10 +67,9 @@
|
||||
# the `sharedName`.
|
||||
#
|
||||
# Errors with an `index` can also optionally contain user-facing documentation
|
||||
# for the problem (documentation), which will be extracted to
|
||||
# `pkg/analyzer/tool/diagnostics/diagnostics.md`, as well as internal
|
||||
# documentation (comment), which will be included in the code generated for the
|
||||
# analyzer.
|
||||
# for the problem (documentation), which dart.dev will extract,
|
||||
# as well as internal documentation (comment), which will be included in
|
||||
# the code generated for the analyzer.
|
||||
#
|
||||
# In some cases a message is internal to the frontend, and no meaningful
|
||||
# analyzer code can be provided. In such cases set `frontendInternal: true`.
|
||||
|
||||
@@ -266,15 +266,7 @@ control_flow_in_finally:
|
||||
...
|
||||
```
|
||||
|
||||
If you do add or change a lint's diagnostic documentation,
|
||||
make sure to regenerate the resulting [`diagnostics.md` file][]:
|
||||
|
||||
```
|
||||
dart run pkg/analyzer/tool/diagnostics/generate.dart
|
||||
```
|
||||
|
||||
[documenting diagnostics]: ../../analyzer/doc/implementation/diagnostics.md#document-the-diagnostic
|
||||
[`diagnostics.md` file]: ../../analyzer/tool/diagnostics/diagnostics.md
|
||||
|
||||
## Mechanics
|
||||
|
||||
@@ -399,7 +391,6 @@ make sure all generated files are up to date.
|
||||
|
||||
```
|
||||
dart run pkg/linter/tool/generate_lints.dart
|
||||
dart run pkg/analyzer/tool/diagnostics/generate.dart
|
||||
```
|
||||
|
||||
### Utilities
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
# make sure to regenerate supporting classes by running:
|
||||
#
|
||||
# dart run pkg/linter/tool/generate_lints.dart
|
||||
#
|
||||
# If you updated or added a `documentation` property,
|
||||
# make sure to regenerate the documentation by running:
|
||||
#
|
||||
# dart run pkg/analyzer/tool/diagnostics/generate.dart
|
||||
|
||||
# There is a fixed set of categories:
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user