Skip to content

Commit

Permalink
Fix document generation, eliminate template support from snippets too…
Browse files Browse the repository at this point in the history
…l. (flutter#147893)

## Description

This fixes the API doc generation that I broke when I moved the snippets tool into the framework.

It removes the last of the template support (properly this time), and makes sure all of the tests pass.

## Related Issues
 - flutter#144408
 - flutter#147609
 - flutter#147645

## Tests
 - Fixed tests, including smoke test of doc generation.
  • Loading branch information
gspencergoog authored and itsjustkevin committed May 8, 2024
1 parent 9ced09e commit f195fed
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 265 deletions.
27 changes: 0 additions & 27 deletions dev/snippets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,33 +113,6 @@ demonstrate the API's functionality in a sample application, or used with the
`dartpad` samples are embedded into the API docs web page and are live
applications in the API documentation.

```dart
/// {@tool sample --template=stateless_widget_material}
/// This example shows how to make a simple [FloatingActionButton] in a
/// [Scaffold], with a pink [backgroundColor] and a thumbs up [Icon].
///
/// ```dart
/// Widget build(BuildContext context) {
/// return Scaffold(
/// appBar: AppBar(
/// title: Text('Floating Action Button Sample'),
/// ),
/// body: Center(
/// child: Text('Press the button below!')
/// ),
/// floatingActionButton: FloatingActionButton(
/// onPressed: () {
/// // Add your onPressed code here!
/// },
/// child: Icon(Icons.thumb_up),
/// backgroundColor: Colors.pink,
/// ),
/// );
/// }
/// ```
/// {@end-tool}
```
This uses the skeleton for [application](https://github.com/flutter/flutter/blob/main/dev/snippets/config/skeletons/sample.html)
snippets in the Flutter repo.

Expand Down
15 changes: 3 additions & 12 deletions dev/snippets/bin/snippets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const String _kOutputDirectoryOption = 'output-directory';
const String _kOutputOption = 'output';
const String _kPackageOption = 'package';
const String _kSerialOption = 'serial';
const String _kTemplateOption = 'template';
const String _kTypeOption = 'type';

class GitStatusFailed implements Exception {
Expand Down Expand Up @@ -126,22 +125,14 @@ void main(List<String> argList) {
allowed: sampleTypes,
allowedHelp: <String, String>{
'dartpad':
'Produce a code sample application complete with embedding the sample in an '
'application template for using in Dartpad.',
'Produce a code sample application for using in Dartpad.',
'sample':
'Produce a code sample application complete with embedding the sample in an '
'application template.',
'Produce a code sample application.',
'snippet':
'Produce a nicely formatted piece of sample code. Does not embed the '
'sample into an application template.',
'Produce a nicely formatted piece of sample code.',
},
help: 'The type of snippet to produce.',
);
// TODO(goderbauer): Remove template support, this is no longer used.
parser.addOption(
_kTemplateOption,
help: 'The name of the template to inject the code into.',
);
parser.addOption(
_kOutputOption,
help: 'The output name for the generated sample application. Overrides '
Expand Down
10 changes: 0 additions & 10 deletions dev/snippets/lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class SnippetConfiguration {
const SnippetConfiguration({
required this.configDirectory,
required this.skeletonsDirectory,
required this.templatesDirectory,
this.filesystem = const LocalFileSystem(),
});

Expand All @@ -25,10 +24,6 @@ class SnippetConfiguration {
/// and returned to dartdoc for insertion in the output.
final Directory skeletonsDirectory;

/// The directory containing the code templates that can be referenced by the
/// dartdoc.
final Directory templatesDirectory;

/// Gets the skeleton file to use for the given [SampleType] and DartPad
/// preference.
File getHtmlSkeletonFile(String type) {
Expand All @@ -47,11 +42,6 @@ class FlutterRepoSnippetConfiguration extends SnippetConfiguration {
const <String>['dev', 'snippets', 'config']),
skeletonsDirectory: _underRoot(filesystem, flutterRoot,
const <String>['dev', 'snippets', 'config', 'skeletons']),
templatesDirectory: _underRoot(
filesystem,
flutterRoot,
const <String>['dev', 'snippets', 'config', 'templates'],
),
);

final Directory flutterRoot;
Expand Down
6 changes: 3 additions & 3 deletions dev/snippets/lib/src/data_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class SourceLine {

/// A class containing the name and contents associated with a code block inside of a
/// code sample, for named injection into a template.
class TemplateInjection {
TemplateInjection(this.name, this.contents, {this.language = ''});
class SkeletonInjection {
SkeletonInjection(this.name, this.contents, {this.language = ''});
final String name;
final List<SourceLine> contents;
final String language;
Expand Down Expand Up @@ -137,7 +137,7 @@ abstract class CodeSample {
String get element => start.element ?? '';
String output = '';
Map<String, Object?> metadata = <String, Object?>{};
List<TemplateInjection> parts = <TemplateInjection>[];
List<SkeletonInjection> parts = <SkeletonInjection>[];
SourceLine get start => input.isEmpty ? _lineProto : input.first;

String get template {
Expand Down
28 changes: 10 additions & 18 deletions dev/snippets/lib/src/import_sorter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ class _DirectiveInfo implements Comparable<_DirectiveInfo> {
if (priority == other.priority) {
return _compareUri(uri, other.uri);
}
return priority.ordinal - other.priority.ordinal;
return priority.index - other.priority.index;
}

@override
Expand Down Expand Up @@ -387,23 +387,15 @@ class _DirectiveInfo implements Comparable<_DirectiveInfo> {
}

enum _DirectivePriority {
IMPORT_SDK('IMPORT_SDK', 0),
IMPORT_PKG('IMPORT_PKG', 1),
IMPORT_OTHER('IMPORT_OTHER', 2),
IMPORT_REL('IMPORT_REL', 3),
EXPORT_SDK('EXPORT_SDK', 4),
EXPORT_PKG('EXPORT_PKG', 5),
EXPORT_OTHER('EXPORT_OTHER', 6),
EXPORT_REL('EXPORT_REL', 7),
PART('PART', 8);

const _DirectivePriority(this.name, this.ordinal);

final String name;
final int ordinal;

@override
String toString() => name;
IMPORT_SDK,
IMPORT_PKG,
IMPORT_OTHER,
IMPORT_REL,
EXPORT_SDK,
EXPORT_PKG,
EXPORT_OTHER,
EXPORT_REL,
PART
}

/// SourceEdit
Expand Down
100 changes: 16 additions & 84 deletions dev/snippets/lib/src/snippet_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,9 @@ class SnippetGenerator {
static DartFormatter formatter =
DartFormatter(pageWidth: 80, fixes: StyleFix.all);

/// Gets the path to the template file requested.
File? getTemplatePath(String templateName, {Directory? templatesDir}) {
final Directory templateDir =
templatesDir ?? configuration.templatesDirectory;
final File templateFile = configuration.filesystem
.file(path.join(templateDir.path, '$templateName.tmpl'));
return templateFile.existsSync() ? templateFile : null;
}

/// Returns an iterable over the template files available in the templates
/// directory in the configuration.
Iterable<File> getAvailableTemplates() sync* {
final Directory templatesDir = configuration.templatesDirectory;
for (final File file in templatesDir.listSync().whereType<File>()) {
if (file.basename.endsWith('.tmpl')) {
yield file;
}
}
}

/// Interpolates the [injections] into an HTML skeleton file.
///
/// Similar to interpolateTemplate, but we are only looking for `code-`
/// components, and we care about the order of the injections.
/// The order of the injections is important.
///
/// Takes into account the [type] and doesn't substitute in the id and the app
/// if not a [SnippetType.sample] snippet.
Expand All @@ -77,7 +56,7 @@ class SnippetGenerator {
final List<String> codeParts = <String>[];
const HtmlEscape htmlEscape = HtmlEscape();
String? language;
for (final TemplateInjection injection in sample.parts) {
for (final SkeletonInjection injection in sample.parts) {
if (!injection.name.startsWith('code')) {
continue;
}
Expand Down Expand Up @@ -165,7 +144,7 @@ class SnippetGenerator {
/// into valid Dart code.
List<SourceLine> _processBlocks(CodeSample sample) {
final List<SourceLine> block = sample.parts
.expand<SourceLine>((TemplateInjection injection) => injection.contents)
.expand<SourceLine>((SkeletonInjection injection) => injection.contents)
.toList();
if (block.isEmpty) {
return <SourceLine>[];
Expand Down Expand Up @@ -233,11 +212,11 @@ class SnippetGenerator {
}
/// Parses the input for the various code and description segments, and
/// returns a set of template injections in the order found.
List<TemplateInjection> parseInput(CodeSample sample) {
/// returns a set of skeleton injections in the order found.
List<SkeletonInjection> parseInput(CodeSample sample) {
bool inCodeBlock = false;
final List<SourceLine> description = <SourceLine>[];
final List<TemplateInjection> components = <TemplateInjection>[];
final List<SkeletonInjection> components = <SkeletonInjection>[];
String? language;
final RegExp codeStartEnd =
RegExp(r'^\s*```(?<language>[-\w]+|[-\w]+ (?<section>[-\w]+))?\s*$');
Expand All @@ -249,12 +228,12 @@ class SnippetGenerator {
if (match.namedGroup('language') != null) {
language = match[1];
if (match.namedGroup('section') != null) {
components.add(TemplateInjection(
components.add(SkeletonInjection(
'code-${match.namedGroup('section')}', <SourceLine>[],
language: language!));
} else {
components.add(
TemplateInjection('code', <SourceLine>[], language: language!));
SkeletonInjection('code', <SourceLine>[], language: language!));
}
} else {
language = null;
Expand Down Expand Up @@ -286,9 +265,9 @@ class SnippetGenerator {
lastWasWhitespace = onlyWhitespace;
}
sample.description = descriptionLines.join('\n').trimRight();
sample.parts = <TemplateInjection>[
sample.parts = <SkeletonInjection>[
if (sample is SnippetSample)
TemplateInjection('#assumptions', sample.assumptions),
SkeletonInjection('#assumptions', sample.assumptions),
...components,
];
return sample.parts;
Expand Down Expand Up @@ -327,10 +306,6 @@ class SnippetGenerator {
///
/// The optional `output` is the file to write the generated sample code to.
///
/// If `addSectionMarkers` is true, then markers will be added before and
/// after each template section in the output. This is intended to facilitate
/// editing of the sample during the authoring process.
///
/// If `includeAssumptions` is true, then the block in the "Examples can
/// assume:" block will also be included in the output.
///
Expand All @@ -341,58 +316,16 @@ class SnippetGenerator {
String? copyright,
String? description,
bool formatOutput = true,
bool addSectionMarkers = false,
bool includeAssumptions = false,
}) {
sample.metadata['copyright'] ??= copyright;
final List<TemplateInjection> snippetData = parseInput(sample);
final List<SkeletonInjection> snippetData = parseInput(sample);
sample.description = description ?? sample.description;
sample.metadata['description'] = _getDescription(sample);
switch (sample.runtimeType) {
switch (sample) {
case DartpadSample _:
case ApplicationSample _:
String app;
if (sample.sourceFile == null) {
final String templateName = sample.template;
if (templateName.isEmpty) {
io.stderr
.writeln('Non-linked samples must have a --template argument.');
io.exit(1);
}
final Directory templatesDir = configuration.templatesDirectory;
File? templateFile;
templateFile =
getTemplatePath(templateName, templatesDir: templatesDir);
if (templateFile == null) {
io.stderr.writeln(
'The template $templateName was not found in the templates '
'directory ${templatesDir.path}');
io.exit(1);
}
final String templateContents = _loadFileAsUtf8(templateFile);
final String templateRelativePath =
templateFile.absolute.path.contains(flutterRoot.absolute.path)
? path.relative(templateFile.absolute.path,
from: flutterRoot.absolute.path)
: templateFile.absolute.path;
final String templateHeader = '''
// Template: $templateRelativePath
//
// Comment lines marked with "▼▼▼" and "▲▲▲" are used for authoring
// of samples, and may be ignored if you are just exploring the sample.
''';
app = interpolateTemplate(
snippetData,
addSectionMarkers
? '$templateHeader\n$templateContents'
: templateContents,
sample.metadata,
addSectionMarkers: addSectionMarkers,
addCopyright: copyright != null,
);
} else {
app = sample.sourceFileContents;
}
final String app = sample.sourceFileContents;
sample.output = app;
if (formatOutput) {
final DartFormatter formatter =
Expand Down Expand Up @@ -421,28 +354,27 @@ class SnippetGenerator {
metadataFile.writeAsStringSync(jsonEncoder.convert(metadata));
}
case SnippetSample _:
if (sample is SnippetSample) {
String app;
if (sample.sourceFile == null) {
String templateContents;
if (includeAssumptions) {
templateContents =
'${headers.map<String>((SourceLine line) => line.text).join('\n')}\n{{#assumptions}}\n{{description}}\n{{code}}';
'${headers.map<String>((SourceLine line) {
return line.text;
}).join('\n')}\n{{#assumptions}}\n{{description}}\n{{code}}';
} else {
templateContents = '{{description}}\n{{code}}';
}
app = interpolateTemplate(
snippetData,
templateContents,
sample.metadata,
addSectionMarkers: addSectionMarkers,
addCopyright: copyright != null,
);
} else {
app = sample.inputAsString;
}
sample.output = app;
}
}
return sample.output;
}
Expand Down
2 changes: 1 addition & 1 deletion dev/snippets/lib/src/snippet_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class SnippetDartdocParser {
}
parseComment(element);
for (final CodeSample sample in element.samples) {
switch (sample.runtimeType) {
switch (sample) {
case DartpadSample _:
dartpadCount++;
case ApplicationSample _:
Expand Down

0 comments on commit f195fed

Please sign in to comment.