Skip to content

Remove Templates.fromContext and as a result, make code more synchronous #4060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions bin/dartdoc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// 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:async';

import 'package:dartdoc/src/dartdoc.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/model/model.dart';
Expand All @@ -12,7 +10,7 @@ import 'package:dartdoc/src/package_meta.dart';

/// Analyzes Dart files and generates a representation of included libraries,
/// classes, and members. Uses the current directory to look for libraries.
Future<void> main(List<String> arguments) async {
void main(List<String> arguments) {
var config = parseOptions(pubPackageMetaProvider, arguments);
if (config == null) {
// Do not run dartdoc as there was either a fatal error parsing options, or
Expand All @@ -23,7 +21,7 @@ Future<void> main(List<String> arguments) async {
final packageBuilder =
PubPackageBuilder(config, pubPackageMetaProvider, packageConfigProvider);
final dartdoc = config.generateDocs
? await Dartdoc.fromContext(config, packageBuilder)
? Dartdoc.fromContext(config, packageBuilder)
: Dartdoc.withEmptyGenerator(config, packageBuilder);
dartdoc.executeGuarded();
}
11 changes: 5 additions & 6 deletions lib/src/dartdoc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class Dartdoc {
set generator(Generator newGenerator) => _generator = newGenerator;

/// Factory method that builds Dartdoc with an empty generator.
static Dartdoc withEmptyGenerator(
factory Dartdoc.withEmptyGenerator(
DartdocOptionContext config,
PackageBuilder packageBuilder,
) {
Expand All @@ -157,12 +157,11 @@ class Dartdoc {
);
}

/// Asynchronous factory method that builds Dartdoc with a generator
/// determined by the given context.
static Future<Dartdoc> fromContext(
/// Builds Dartdoc with a generator determined by [context].
factory Dartdoc.fromContext(
DartdocGeneratorOptionContext context,
PackageBuilder packageBuilder,
) async {
) {
var resourceProvider = context.resourceProvider;
var outputPath = resourceProvider.pathContext.absolute(context.output);
var outputDir = resourceProvider.getFolder(outputPath)..create();
Expand All @@ -175,7 +174,7 @@ class Dartdoc {
return Dartdoc._(
context,
outputDir,
await initHtmlGenerator(context, writer: writer),
initHtmlGenerator(context, writer: writer),
packageBuilder,
);
}
Expand Down
11 changes: 3 additions & 8 deletions lib/src/generator/html_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,13 @@ import 'package:dartdoc/src/generator/template_data.dart';
import 'package:dartdoc/src/generator/templates.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/runtime_stats.dart';
import 'package:meta/meta.dart';

/// Creates a [Generator] with an [HtmlGeneratorBackend] backend.
///
/// [forceRuntimeTemplates] should only be given `true` during tests.
Future<Generator> initHtmlGenerator(
Generator initHtmlGenerator(
DartdocGeneratorOptionContext context, {
required FileWriter writer,
@visibleForTesting bool forceRuntimeTemplates = false,
}) async {
var templates = await Templates.fromContext(context,
forceRuntimeTemplates: forceRuntimeTemplates);
}) {
var templates = HtmlAotTemplates();
var options = DartdocGeneratorBackendOptions.fromContext(context);
var backend = HtmlGeneratorBackend(
options, templates, writer, context.resourceProvider);
Expand Down
23 changes: 1 addition & 22 deletions lib/src/generator/resource_loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,12 @@
/// Make it possible to load resources from the dartdoc code repository.
library;

import 'dart:convert' show utf8;
import 'dart:isolate' show Isolate;

import 'package:analyzer/file_system/file_system.dart';
import 'package:meta/meta.dart';

extension ResourceLoader on ResourceProvider {
/// Loads a `package:` resource as a String.
Future<String> loadResourceAsString(String path) async {
var bytes = await loadResourceAsBytes(path);

return utf8.decode(bytes);
}

/// Loads a `package:` resource as an [List<int>].
Future<List<int>> loadResourceAsBytes(String path) async {
if (!path.startsWith('package:')) {
throw ArgumentError('path must begin with package:');
}

return (await getResourceFile(path)).readAsBytesSync();
}

Future<File> getResourceFile(String path) async {
var uri = await resolveResourceUri(Uri.parse(path));
return getFile(uri.toFilePath());
}

Future<Folder> getResourceFolder(String path) async {
var uri = await resolveResourceUri(Uri.parse(path));
return getFolder(uri.toFilePath());
Expand Down
76 changes: 2 additions & 74 deletions lib/src/generator/templates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@
@Renderer(#renderTypedef, Context<TypedefTemplateData>(), 'typedef')
library;

import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/failure.dart';
import 'package:dartdoc/src/generator/resource_loader.dart';
import 'package:dartdoc/src/generator/template_data.dart';
import 'package:dartdoc/src/generator/templates.aot_renderers_for_html.dart'
as aot_renderers_for_html;
Expand Down Expand Up @@ -115,23 +111,6 @@ abstract class Templates {
String renderSidebarForLibrary(TemplateDataWithLibrary<Documentable> context);
String renderTopLevelProperty(TopLevelPropertyTemplateData context);
String renderTypedef(TypedefTemplateData context);

/// Creates a [Templates] instance from the default set of templates.
///
/// [forceRuntimeTemplates] should only be given `true` during tests.
static Future<Templates> fromContext(DartdocGeneratorOptionContext context,
// TODO(srawlins): Remove this option, as runtime templates are no longer
// supported.
{bool forceRuntimeTemplates = false}) async {
if (forceRuntimeTemplates) {
var directory = await context.resourceProvider
.getResourceFolder('package:dartdoc/templates');
return RuntimeTemplates._create(directory,
resourceProvider: context.resourceProvider);
} else {
return HtmlAotTemplates();
}
}
}

/// The [Templates] implementation which uses the render functions generated
Expand Down Expand Up @@ -221,6 +200,8 @@ class HtmlAotTemplates implements Templates {
}

/// The collection of [Template] objects parsed at runtime.
// TODO(srawlins): Remove this class, and `templates.runtime_renderers.dart`, as
// runtime templates are no longer supported.
class RuntimeTemplates implements Templates {
@override
String renderCategory(CategoryTemplateData context) =>
Expand Down Expand Up @@ -325,59 +306,6 @@ class RuntimeTemplates implements Templates {
final Template _topLevelPropertyTemplate;
final Template _typedefTemplate;

/// Creates a [Templates] from a custom set of template files, found in [dir].
static Future<Templates> _create(Folder dir,
{required ResourceProvider resourceProvider}) async {
Future<Template> loadTemplate(String templatePath) {
var templateFile = dir.getChildAssumingFile('$templatePath.html');
if (!templateFile.exists) {
throw DartdocFailure(
'Missing required template file: $templatePath.html');
}
return Template.parse(templateFile,
partialResolver: (String partialName) async =>
dir.getChildAssumingFile('_$partialName.html'));
}

var indexTemplate = await loadTemplate('index');
var libraryTemplate = await loadTemplate('library');
var searchPageTemplate = await loadTemplate('search');
var sidebarContainerTemplate = await loadTemplate('_sidebar_for_container');
var sidebarLibraryTemplate = await loadTemplate('_sidebar_for_library');
var categoryTemplate = await loadTemplate('category');
var classTemplate = await loadTemplate('class');
var constructorTemplate = await loadTemplate('constructor');
var enumTemplate = await loadTemplate('enum');
var errorTemplate = await loadTemplate('404error');
var extensionTemplate = await loadTemplate('extension');
var functionTemplate = await loadTemplate('function');
var methodTemplate = await loadTemplate('method');
var mixinTemplate = await loadTemplate('mixin');
var propertyTemplate = await loadTemplate('property');
var topLevelPropertyTemplate = await loadTemplate('top_level_property');
var typeDefTemplate = await loadTemplate('typedef');

return RuntimeTemplates._(
categoryTemplate,
libraryTemplate,
classTemplate,
constructorTemplate,
enumTemplate,
errorTemplate,
extensionTemplate,
functionTemplate,
indexTemplate,
methodTemplate,
mixinTemplate,
propertyTemplate,
searchPageTemplate,
sidebarContainerTemplate,
sidebarLibraryTemplate,
topLevelPropertyTemplate,
typeDefTemplate,
);
}

RuntimeTemplates._(
this._categoryTemplate,
this._libraryTemplate,
Expand Down
8 changes: 4 additions & 4 deletions test/dartdoc_test_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ $libraryContent
.named(libraryName);
}

Future<Dartdoc> buildDartdoc({
Dartdoc buildDartdoc({
List<String> excludeLibraries = const [],
List<String> additionalArguments = const [],
bool skipUnreachableSdkLibraries = true,
bool useJson = false,
}) async {
}) {
final dir = resourceProvider.getFolder(resourceProvider.pathContext
.absolute(resourceProvider.pathContext.normalize(packagePath)));
final context = await generatorContextFromArgv([
final context = generatorContextFromArgv([
'--input',
dir.path,
'--output',
Expand All @@ -165,7 +165,7 @@ $libraryContent
outSink: outBuffer,
errSink: errBuffer,
);
return await Dartdoc.fromContext(context, packageBuilder);
return Dartdoc.fromContext(context, packageBuilder);
}

/// The real offset in a library generated with [bootPackageWithLibrary].
Expand Down
24 changes: 11 additions & 13 deletions test/end2end/dartdoc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// 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:async';

import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/src/dartdoc.dart' show Dartdoc, DartdocResults;
import 'package:dartdoc/src/dartdoc_options.dart';
Expand Down Expand Up @@ -63,13 +61,13 @@ void main() {
tempDir.delete();
});

Future<Dartdoc> buildDartdoc(
List<String> argv, Folder packageRoot, Folder tempDir) async {
var context = await generatorContextFromArgv(
Dartdoc buildDartdoc(
List<String> argv, Folder packageRoot, Folder tempDir) {
var context = generatorContextFromArgv(
[...argv, '--input', packageRoot.path, '--output', tempDir.path],
pubPackageMetaProvider);

return await Dartdoc.fromContext(
return Dartdoc.fromContext(
context,
PubPackageBuilder(
context, pubPackageMetaProvider, PhysicalPackageConfigProvider(),
Expand All @@ -79,7 +77,7 @@ void main() {

test('errors generate errors even when warnings are off', () async {
var dartdoc =
await buildDartdoc(['--allow-tools'], testPackageToolError, tempDir);
buildDartdoc(['--allow-tools'], testPackageToolError, tempDir);
var results = await dartdoc.generateDocsBase();
var p = results.packageGraph;
var unresolvedToolErrors = p.packageWarningCounter.countedWarnings.values
Expand All @@ -93,8 +91,8 @@ void main() {
});

test('basic interlinking test', () async {
var dartdoc = await buildDartdoc(
['--exclude-packages=args'], _testPackageDir, tempDir);
var dartdoc =
buildDartdoc(['--exclude-packages=args'], _testPackageDir, tempDir);
var results = await dartdoc.generateDocs();
var p = results.packageGraph;
var meta = p.publicPackages.firstWhere((p) => p.name == 'meta');
Expand Down Expand Up @@ -123,7 +121,7 @@ void main() {

setUpAll(() async {
tempDir = _resourceProvider.createSystemTemp('dartdoc.test.');
var dartdoc = await buildDartdoc([], _testPackageDir, tempDir);
var dartdoc = buildDartdoc([], _testPackageDir, tempDir);
results = await dartdoc.generateDocs();
});

Expand All @@ -145,7 +143,7 @@ void main() {
test('generate docs for ${path.basename(_testPackageBadDir.path)} fails',
skip: 'Blocked on getting analysis errors with correct interpretation '
'from analysis_options', () async {
var dartdoc = await buildDartdoc([], _testPackageBadDir, tempDir);
var dartdoc = buildDartdoc([], _testPackageBadDir, tempDir);

try {
await dartdoc.generateDocs();
Expand All @@ -156,7 +154,7 @@ void main() {
});

test('generate docs for package with embedder yaml', () async {
var dartdoc = await buildDartdoc([], _testSkyEnginePackage, tempDir);
var dartdoc = buildDartdoc([], _testSkyEnginePackage, tempDir);

var results = await dartdoc.generateDocs();
expect(results.packageGraph, isNotNull);
Expand Down Expand Up @@ -188,7 +186,7 @@ void main() {

test('rel canonical prefix does not include base href', () async {
final prefix = 'foo.bar/baz';
var dartdoc = await buildDartdoc(
var dartdoc = buildDartdoc(
['--rel-canonical-prefix', prefix], _testPackageDir, tempDir);
await dartdoc.generateDocsBase();

Expand Down
Loading