Skip to content

Commit 460e22f

Browse files
gspencergoogjcollins-g
authored andcommitted
Added passing of additional metadata about element to tool, and tests. (#1801)
1 parent 10125d0 commit 460e22f

File tree

17 files changed

+123
-35
lines changed

17 files changed

+123
-35
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.24.1-dev
2+
* Added more metadata (element name, project name, etc.) to external tool invocations.
3+
14
## 0.24.0
25
* Add 'override' to feature list for members which override a superclass (#981)
36
* Support many options via dartdoc_options.yaml (#1674)

lib/src/model.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3953,7 +3953,21 @@ abstract class ModelElement extends Canonicalization
39533953
'Must specify a tool to execute for the @tool directive.');
39543954
return '';
39553955
}
3956-
return runner.run(args, basicMatch[2]);
3956+
3957+
return runner.run(args,
3958+
content: basicMatch[2],
3959+
environment: {
3960+
'SOURCE_LINE': lineAndColumn?.item1?.toString(),
3961+
'SOURCE_COLUMN': lineAndColumn?.item2?.toString(),
3962+
'SOURCE_PATH': (sourceFileName == null ||
3963+
package?.packagePath == null)
3964+
? null
3965+
: pathLib.relative(sourceFileName, from: package.packagePath),
3966+
'PACKAGE_PATH': package?.packagePath,
3967+
'PACKAGE_NAME': package?.name,
3968+
'LIBRARY_NAME': library?.fullyQualifiedName,
3969+
'ELEMENT_NAME': fullyQualifiedNameWithoutLibrary,
3970+
}..removeWhere((key, value) => value == null));
39573971
});
39583972
} finally {
39593973
runner.dispose();

lib/src/tool_runner.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ class ToolRunner {
5757
///
5858
/// The [args] must not be null, and it must have at least one member (the name
5959
/// of the tool).
60-
String run(List<String> args, [String content]) {
60+
String run(List<String> args,
61+
{String content, Map<String, String> environment}) {
6162
assert(args != null);
6263
assert(args.isNotEmpty);
6364
content ??= '';
65+
environment ??= <String, String>{};
6466
var tool = args.removeAt(0);
6567
if (!toolConfiguration.tools.containsKey(tool)) {
6668
_error('Unable to find definition for tool "$tool" in tool map. '
@@ -86,18 +88,28 @@ class ToolRunner {
8688
var tmpFile = _createTemporaryFile();
8789
tmpFile.writeAsStringSync(content);
8890

89-
// Substitute the temp filename for the "$INPUT" token.
90-
var fileToken = new RegExp(r'\$INPUT\b');
91+
// Substitute the temp filename for the "$INPUT" token, and all of the
92+
// other environment variables.
93+
// Variables are allowed to either be in $(VAR) form, or $VAR form.
94+
var envWithInput = {'INPUT': tmpFile.absolute.path}..addAll(environment);
95+
var substitutions = envWithInput.map<RegExp, String>((key, value) {
96+
String escapedKey = RegExp.escape(key);
97+
return MapEntry(RegExp('\\\$(\\($escapedKey\\)|$escapedKey\\b)'), value);
98+
});
9199
var argsWithInput = <String>[];
92100
for (var arg in args) {
93-
argsWithInput.add(arg.replaceAll(fileToken, tmpFile.absolute.path));
101+
var newArg = arg;
102+
substitutions
103+
.forEach((regex, value) => newArg = newArg.replaceAll(regex, value));
104+
argsWithInput.add(newArg);
94105
}
95106

96107
argsWithInput = toolArgs + argsWithInput;
97108
final commandPath = argsWithInput.removeAt(0);
98109
String commandString() => ([commandPath] + argsWithInput).join(' ');
99110
try {
100-
var result = Process.runSync(commandPath, argsWithInput);
111+
var result = Process.runSync(commandPath, argsWithInput,
112+
environment: envWithInput);
101113
if (result.exitCode != 0) {
102114
_error('Tool "$tool" returned non-zero exit code '
103115
'(${result.exitCode}) when run as '

lib/src/version.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
// Generated code. Do not modify.
2-
const packageVersion = '0.24.0';
2+
const packageVersion = '0.24.1-dev';

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: dartdoc
22
# Also update the `version` field in lib/dartdoc.dart.
3-
version: 0.24.0
3+
version: 0.24.1-dev
44
author: Dart Team <[email protected]>
55
description: A documentation generator for Dart.
66
homepage: https://github.com/dart-lang/dartdoc

test/model_test.dart

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,30 +83,58 @@ void main() {
8383
Method invokeTool;
8484
Method invokeToolNoInput;
8585

86-
setUp(() {
86+
setUpAll(() {
8787
toolUser = exLibrary.classes.firstWhere((c) => c.name == 'ToolUser');
8888
invokeTool =
8989
toolUser.allInstanceMethods.firstWhere((m) => m.name == 'invokeTool');
9090
invokeToolNoInput = toolUser.allInstanceMethods
9191
.firstWhere((m) => m.name == 'invokeToolNoInput');
9292
packageGraph.allLocalModelElements.forEach((m) => m.documentation);
9393
});
94-
test("can invoke a tool", () {
94+
test('can invoke a tool and pass args and environment', () {
95+
expect(invokeTool.documentation, contains('--file=<INPUT_FILE>'));
9596
expect(
9697
invokeTool.documentation,
9798
contains(
98-
'''Args: [--file=<INPUT_FILE>, --special= |\\[]!@#\\"\'\$%^&*()_+]'''));
99+
new RegExp(r'--source=lib[/\\]example\.dart_[0-9]+_[0-9]+, ')));
100+
expect(
101+
invokeTool.documentation,
102+
contains(new RegExp(
103+
r'--package-path=<PACKAGE_PATH>, ')));
104+
expect(
105+
invokeTool.documentation, contains('--package-name=test_package, '));
106+
expect(invokeTool.documentation, contains('--library-name=ex, '));
107+
expect(invokeTool.documentation,
108+
contains('--element-name=ToolUser.invokeTool, '));
109+
expect(invokeTool.documentation,
110+
contains(r'''--special= |\[]!@#\"'$%^&*()_+]'''));
111+
expect(invokeTool.documentation, contains('INPUT: <INPUT_FILE>'));
112+
expect(invokeTool.documentation,
113+
contains(new RegExp('SOURCE_LINE: [0-9]+, ')));
114+
expect(invokeTool.documentation,
115+
contains(new RegExp('SOURCE_COLUMN: [0-9]+, ')));
116+
expect(invokeTool.documentation,
117+
contains(new RegExp(r'SOURCE_PATH: lib[/\\]example\.dart, ')));
118+
expect(
119+
invokeTool.documentation,
120+
contains(new RegExp(
121+
r'PACKAGE_PATH: <PACKAGE_PATH>, ')));
122+
expect(
123+
invokeTool.documentation, contains('PACKAGE_NAME: test_package, '));
124+
expect(invokeTool.documentation, contains('LIBRARY_NAME: ex, '));
125+
expect(invokeTool.documentation,
126+
contains('ELEMENT_NAME: ToolUser.invokeTool}'));
99127
expect(invokeTool.documentation, contains('## `Yes it is a [Dog]!`'));
100128
});
101-
test("can invoke a tool and add a reference link", () {
129+
test('can invoke a tool and add a reference link', () {
102130
expect(invokeTool.documentation,
103131
contains('Yes it is a [Dog]! Is not a [ToolUser].'));
104132
expect(invokeTool.documentationAsHtml,
105-
contains(r'<a href="ex/ToolUser-class.html">ToolUser</a>'));
133+
contains('<a href="ex/ToolUser-class.html">ToolUser</a>'));
106134
expect(invokeTool.documentationAsHtml,
107135
contains('<a href="ex/Dog-class.html">Dog</a>'));
108136
});
109-
test(r"can invoke a tool with no $INPUT or args", () {
137+
test(r'can invoke a tool with no $INPUT or args', () {
110138
expect(invokeToolNoInput.documentation, contains('Args: []'));
111139
expect(invokeToolNoInput.documentation,
112140
isNot(contains('This text should not appear in the output')));

test/tool_runner_test.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,24 @@ void main() {
4444
test('can invoke a Dart tool', () {
4545
var result = runner.run(
4646
['drill', r'--file=$INPUT'],
47-
'TEST INPUT',
47+
content: 'TEST INPUT',
4848
);
4949
expect(errors, isEmpty);
50-
expect(result, contains(new RegExp(r'Args: \[--file=<INPUT_FILE>]')));
50+
expect(result, contains('--file=<INPUT_FILE>'));
5151
expect(result, contains('## `TEST INPUT`'));
5252
});
5353
test('can invoke a non-Dart tool', () {
5454
String result = runner.run(
5555
['non_dart', '--version'],
56-
'TEST INPUT',
56+
content: 'TEST INPUT',
5757
);
5858
expect(errors, isEmpty);
5959
expect(result, isEmpty); // Output is on stderr.
6060
});
6161
test('fails if tool not in tool map', () {
6262
String result = runner.run(
6363
['hammer', r'--file=$INPUT'],
64-
'TEST INPUT',
64+
content: 'TEST INPUT',
6565
);
6666
expect(errors, isNotEmpty);
6767
expect(
@@ -71,7 +71,7 @@ void main() {
7171
test('fails if tool returns non-zero status', () {
7272
String result = runner.run(
7373
['drill', r'--file=/a/missing/file'],
74-
'TEST INPUT',
74+
content: 'TEST INPUT',
7575
);
7676
expect(errors, isNotEmpty);
7777
expect(errors[0], contains('Tool "drill" returned non-zero exit code'));
@@ -80,7 +80,7 @@ void main() {
8080
test("fails if tool in tool map doesn't exist", () {
8181
String result = runner.run(
8282
['missing'],
83-
'TEST INPUT',
83+
content: 'TEST INPUT',
8484
);
8585
expect(errors, isNotEmpty);
8686
expect(errors[0],

testing/test_package/bin/drill.dart

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,43 @@ void main(List<String> argList) {
1414
final ArgParser argParser = ArgParser();
1515
argParser.addOption('file');
1616
argParser.addOption('special');
17+
argParser.addOption('source');
18+
argParser.addOption('package-name');
19+
argParser.addOption('package-path');
20+
argParser.addOption('library-name');
21+
argParser.addOption('element-name');
1722
final ArgResults args = argParser.parse(argList);
23+
// Normalize the filenames, since they include random
24+
// and system-specific components, but make sure they
25+
// match the patterns we expect.
26+
RegExp inputFileRegExp = new RegExp(
27+
r'(--file=)?(.*)([/\\]dartdoc_tools_)([^/\\]+)([/\\]input_)(\d+)');
28+
RegExp packagePathRegExp =
29+
new RegExp(r'(--package-path=)?(.+dartdoc.*[/\\]testing[/\\]test_package)');
30+
31+
final Set<String> variableNames = new Set<String>.from([
32+
'INPUT',
33+
'SOURCE_LINE',
34+
'SOURCE_COLUMN',
35+
'SOURCE_PATH',
36+
'PACKAGE_NAME',
37+
'PACKAGE_PATH',
38+
'LIBRARY_NAME',
39+
'ELEMENT_NAME'
40+
]);
41+
Map<String, String> env = <String, String>{}..addAll(Platform.environment);
42+
env.removeWhere((String key, String value) => !variableNames.contains(key));
43+
env.updateAll(
44+
(key, value) => inputFileRegExp.hasMatch(value) ? '<INPUT_FILE>' : value);
45+
env.updateAll((key, value) =>
46+
packagePathRegExp.hasMatch(value) ? '<PACKAGE_PATH>' : value);
47+
print('Env: ${env}');
1848

19-
// Normalize the filename, since it includes random
20-
// and system-specific components, but make sure it
21-
// matches the pattern we expect.
22-
RegExp filenameRegExp = new RegExp(
23-
r'(--file=)(.*)([/\\]dartdoc_tools_)([^/\\]+)([/\\]input_)(\d+)');
2449
List<String> normalized = argList.map((String arg) {
25-
if (filenameRegExp.hasMatch(arg)) {
50+
if (inputFileRegExp.hasMatch(arg)) {
2651
return '--file=<INPUT_FILE>';
52+
} else if (packagePathRegExp.hasMatch(arg)) {
53+
return '--package-path=<PACKAGE_PATH>';
2754
} else {
2855
return arg;
2956
}

testing/test_package/lib/example.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ abstract class TypedFunctionsWithoutTypedefs {
585585
abstract class ToolUser {
586586
/// Invokes a tool.
587587
///
588-
/// {@tool drill --file="$INPUT" --special=" |\[]!@#\"'$%^&*()_+"}
588+
/// {@tool drill --file="$INPUT" --source="$(SOURCE_PATH)_$(SOURCE_LINE)_$SOURCE_COLUMN" --package-path=$PACKAGE_PATH --package-name=$PACKAGE_NAME --library-name=$LIBRARY_NAME --element-name=$(ELEMENT_NAME) --special=" |\[]!@#\"'$%^&*()_+"}
589589
/// Yes it is a [Dog]!
590590
/// Ok, fine it isn't.
591591
/// {@end-tool}

testing/test_package_docs/__404error.html

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)