Commit a516a24e authored by Ian Hickson's avatar Ian Hickson Committed by Flutter GitHub Bot

Update internal dartdoc snippet documentation (#47017)

parent 90242310
...@@ -2,54 +2,16 @@ ...@@ -2,54 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This script analyzes all the sample code in API docs in the Flutter source. // See ../snippets/README.md for documentation.
//
// It uses the following conventions: // To run this, from the root of the Flutter repository:
// // bin/cache/dart-sdk/bin/dart dev/bots/analyze-sample-code.dart
// Code is denoted by markdown ```dart / ``` markers.
//
// Only code in "## Sample code" or "### Sample code" sections is examined.
// Subheadings can also be specified, as in "## Sample code: foo".
//
// Additionally, code inside of dartdoc snippet and sample blocks
// ({@tool snippet ...}{@end-tool}, and {@tool sample ...}{@end-tool})
// is recognized as sample code. Snippets are processed as separate programs,
// and samples are processed in the same way as "## Sample code" blocks are.
//
// There are several kinds of sample code you can specify:
//
// * Constructor calls, typically showing what might exist in a build method.
// These start with "new" or "const", and will be inserted into an assignment
// expression assigning to a variable of type "dynamic" and followed by a
// semicolon, for the purposes of analysis.
//
// * Class definitions. These start with "class", and are analyzed verbatim.
//
// * Other code. It gets included verbatim, though any line that says "// ..."
// is considered to separate the block into multiple blocks to be processed
// individually.
//
// In addition, you can declare code that should be included in the analysis but
// not shown in the API docs by adding a comment "// Examples can assume:" to
// the file (usually at the top of the file, after the imports), following by
// one or more commented-out lines of code. That code is included verbatim in
// the analysis.
//
// All the sample code of every file is analyzed together. This means you can't
// have two pieces of sample code that define the same example class.
//
// Also, the above means that it's tricky to include verbatim imperative code
// (e.g. a call to a method), since it won't be valid to have such code at the
// top level. Instead, wrap it in a function or even a whole class, or make it a
// valid variable declaration.
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
// To run this: bin/cache/dart-sdk/bin/dart dev/bots/analyze-sample-code.dart
final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script)))); final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
final String _defaultFlutterPackage = path.join(_flutterRoot, 'packages', 'flutter', 'lib'); final String _defaultFlutterPackage = path.join(_flutterRoot, 'packages', 'flutter', 'lib');
final String _flutter = path.join(_flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter'); final String _flutter = path.join(_flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
...@@ -80,6 +42,7 @@ void main(List<String> arguments) { ...@@ -80,6 +42,7 @@ void main(List<String> arguments) {
if (parsedArguments['help'] as bool) { if (parsedArguments['help'] as bool) {
print(argParser.usage); print(argParser.usage);
print('See dev/snippets/README.md for documentation.');
exit(0); exit(0);
} }
...@@ -325,11 +288,11 @@ class SampleChecker { ...@@ -325,11 +288,11 @@ class SampleChecker {
'--input=${inputFile.absolute.path}', '--input=${inputFile.absolute.path}',
...snippet.args, ...snippet.args,
]; ];
if (verbose)
print('Generating snippet for ${snippet.start?.filename}:${snippet.start?.line}'); print('Generating snippet for ${snippet.start?.filename}:${snippet.start?.line}');
final ProcessResult process = _runSnippetsScript(args); final ProcessResult process = _runSnippetsScript(args);
if (verbose) { if (verbose)
stderr.write('${process.stderr}'); stderr.write('${process.stderr}');
}
if (process.exitCode != 0) { if (process.exitCode != 0) {
throw SampleCheckerException( throw SampleCheckerException(
'Unable to create snippet for ${snippet.start.filename}:${snippet.start.line} ' 'Unable to create snippet for ${snippet.start.filename}:${snippet.start.line} '
...@@ -831,8 +794,7 @@ class Line { ...@@ -831,8 +794,7 @@ class Line {
String toString() => '$filename:$line: $code'; String toString() => '$filename:$line: $code';
} }
/// A class to represent a section of sample code, either marked by /// A class to represent a section of sample code, marked by "{@tool sample}...{@end-tool}".
/// "/// ## Sample code" in the comment, or by "{@tool sample}...{@end-tool}".
class Section { class Section {
const Section(this.code); const Section(this.code);
factory Section.combine(List<Section> sections) { factory Section.combine(List<Section> sections) {
......
// Copyright 2014 The Flutter Authors. All rights reserved. // Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -27,7 +27,6 @@ void main() { ...@@ -27,7 +27,6 @@ void main() {
]); ]);
expect(stdoutLines, <String>[ expect(stdoutLines, <String>[
'Found 7 sample code sections.', 'Found 7 sample code sections.',
'Generating snippet for known_broken_documentation.dart:38',
'Starting analysis of samples.', 'Starting analysis of samples.',
'', '',
]); ]);
......
...@@ -13,8 +13,17 @@ in the source code into API documentation, as seen on https://api.flutter.dev/. ...@@ -13,8 +13,17 @@ in the source code into API documentation, as seen on https://api.flutter.dev/.
- [Snippet tool](#snippet-tool) - [Snippet tool](#snippet-tool)
- [Skeletons](#skeletons) - [Skeletons](#skeletons)
- [Test Doc Generation Workflow](#test-doc-generation-workflow) - [Test Doc Generation Workflow](#test-doc-generation-workflow)
## Types of code blocks ## Types of code blocks
There's two kinds of code blocks.
* samples, which are more or less context-free snippets that we
magically determine how to analyze, and
* snippets, which get placed into a full-fledged application, and can
be actually executed inline in the documentation using DartPad.
### Sample Tool ### Sample Tool
![Code sample image](assets/code_sample.png) ![Code sample image](assets/code_sample.png)
...@@ -39,7 +48,48 @@ code. Here is an example of the code `sample` tool in use: ...@@ -39,7 +48,48 @@ code. Here is an example of the code `sample` tool in use:
This will generate sample code that can be copied to the clipboard and added This will generate sample code that can be copied to the clipboard and added
to existing applications. to existing applications.
This uses the skeleton for [sample](config/skeletons/sample.html) snippets. This uses the skeleton for [sample](config/skeletons/sample.html)
snippets when generating the HTML to put into the Dart docs.
#### Analysis
The `../bots/analyze-sample-code.dart` script finds code inside the
`@tool sample` sections and uses the Dart analyzer to check them.
There are several kinds of sample code you can specify:
* Constructor calls, typically showing what might exist in a build
method. These will be inserted into an assignment expression
assigning to a variable of type "dynamic" and followed by a
semicolon, for the purposes of analysis.
* Class definitions. These start with "class", and are analyzed
verbatim.
* Other code. It gets included verbatim, though any line that says
`// ...` is considered to separate the block into multiple blocks
to be processed individually.
The above means that it's tricky to include verbatim imperative code
(e.g. a call to a method), since it won't be valid to have such code
at the top level. Instead, wrap it in a function or even a whole
class, or make it a valid variable declaration.
You can declare code that should be included in the analysis but not
shown in the API docs by adding a comment "// Examples can assume:" to
the file (usually at the top of the file, after the imports),
following by one or more commented-out lines of code. That code is
included verbatim in the analysis. For example:
```dart
// Examples can assume:
// final BuildContext context;
// final String userAvatarUrl;
```
You can assume that the entire Flutter framework and most common
`dart:*` packages are imported and in scope; `dart:math` as `math` and
`dart:ui` as `ui`.
### Snippet Tool ### Snippet Tool
...@@ -99,6 +149,12 @@ flutter app package. ...@@ -99,6 +149,12 @@ flutter app package.
For more information about how to create, use, or update templates, see For more information about how to create, use, or update templates, see
[config/templates/README.md](config/templates/README.md). [config/templates/README.md](config/templates/README.md).
#### Analysis
The `../bots/analyze-sample-code.dart` script finds code inside the
`@tool snippet` sections and uses the Dart analyzer to check them
after applying the specified template.
## Skeletons ## Skeletons
A skeleton (in relation to this tool) is an HTML template into which the Dart A skeleton (in relation to this tool) is an HTML template into which the Dart
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment